From ebb1566a46f2f5b2c06ef0f7ad5f7084dce0aed9 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Tue, 28 Jun 2011 09:43:14 +1000 Subject: [PATCH] strings.Split: make the default to split all. Change the signature of Split to have no count, assuming a full split, and rename the existing Split with a count to SplitN. Do the same to package bytes. Add a gofix module. R=adg, dsymonds, alex.brainman, rsc CC=golang-dev https://golang.org/cl/4661051 --- misc/dashboard/builder/main.go | 8 +-- src/cmd/cgo/gcc.go | 10 +-- src/cmd/cgo/out.go | 2 +- src/cmd/godoc/dirtrees.go | 4 +- src/cmd/godoc/godoc.go | 2 +- src/cmd/godoc/index.go | 2 +- src/cmd/gofix/Makefile | 1 + src/cmd/gofix/main.go | 2 +- src/cmd/gofix/stringssplit.go | 71 +++++++++++++++++++ src/cmd/gofix/stringssplit_test.go | 51 +++++++++++++ src/cmd/gofix/testdata/reflect.template.go.in | 4 +- .../gofix/testdata/reflect.template.go.out | 4 +- src/cmd/gofmt/gofmt_test.go | 4 +- src/cmd/gofmt/rewrite.go | 2 +- src/cmd/goinstall/download.go | 4 +- src/cmd/govet/govet.go | 2 +- src/cmd/goyacc/goyacc.go | 2 +- src/cmd/hgpatch/main.go | 2 +- src/pkg/asn1/common.go | 2 +- src/pkg/bytes/bytes.go | 42 +++++++---- src/pkg/bytes/bytes_test.go | 19 ++++- src/pkg/compress/lzw/reader_test.go | 2 +- src/pkg/crypto/x509/verify.go | 4 +- src/pkg/debug/proc/proc_linux.go | 2 +- src/pkg/exec/exec_test.go | 2 +- src/pkg/exec/lp_plan9.go | 2 +- src/pkg/exec/lp_unix.go | 2 +- src/pkg/exec/lp_windows.go | 4 +- src/pkg/exp/ogle/cmd.go | 2 +- src/pkg/go/ast/print_test.go | 2 +- src/pkg/go/build/dir.go | 2 +- src/pkg/go/doc/comment.go | 2 +- src/pkg/html/token_test.go | 2 +- src/pkg/http/cgi/host.go | 2 +- src/pkg/http/cgi/host_test.go | 2 +- src/pkg/http/cookie.go | 4 +- src/pkg/http/fs.go | 2 +- src/pkg/http/request.go | 8 +-- src/pkg/http/response.go | 2 +- src/pkg/http/server.go | 2 +- src/pkg/http/spdy/read.go | 2 +- src/pkg/http/transfer.go | 4 +- src/pkg/http/transport.go | 4 +- src/pkg/http/url.go | 4 +- src/pkg/mail/message.go | 2 +- src/pkg/mime/mediatype.go | 2 +- src/pkg/patch/patch.go | 2 +- src/pkg/path/filepath/path.go | 2 +- src/pkg/rpc/server.go | 2 +- src/pkg/runtime/debug/stack.go | 2 +- src/pkg/runtime/debug/stack_test.go | 2 +- src/pkg/smtp/smtp.go | 6 +- src/pkg/smtp/smtp_test.go | 4 +- src/pkg/strconv/fp_test.go | 6 +- src/pkg/strings/strings.go | 42 +++++++---- src/pkg/strings/strings_test.go | 22 ++++-- src/pkg/template/execute.go | 2 +- src/pkg/template/parse.go | 2 +- src/pkg/testing/testing.go | 2 +- src/pkg/unicode/maketables.go | 12 ++-- 60 files changed, 296 insertions(+), 120 deletions(-) create mode 100644 src/cmd/gofix/stringssplit.go create mode 100644 src/cmd/gofix/stringssplit_test.go diff --git a/misc/dashboard/builder/main.go b/misc/dashboard/builder/main.go index 9a714fe79fa..bee663d6cff 100644 --- a/misc/dashboard/builder/main.go +++ b/misc/dashboard/builder/main.go @@ -161,7 +161,7 @@ func NewBuilder(builder string) (*Builder, os.Error) { b := &Builder{name: builder} // get goos/goarch from builder string - s := strings.Split(builder, "-", 3) + s := strings.SplitN(builder, "-", 3) if len(s) >= 2 { b.goos, b.goarch = s[0], s[1] } else { @@ -177,7 +177,7 @@ func NewBuilder(builder string) (*Builder, os.Error) { if err != nil { return nil, fmt.Errorf("readKeys %s (%s): %s", b.name, fn, err) } - v := strings.Split(string(c), "\n", -1) + v := strings.Split(string(c), "\n") b.key = v[0] if len(v) >= 3 { b.codeUsername, b.codePassword = v[1], v[2] @@ -392,7 +392,7 @@ func (b *Builder) envvWindows() []string { skip[name] = true } for _, kv := range os.Environ() { - s := strings.Split(kv, "=", 2) + s := strings.SplitN(kv, "=", 2) name := strings.ToUpper(s[0]) switch { case name == "": @@ -602,7 +602,7 @@ var revisionRe = regexp.MustCompile(`^([^ ]+) +[0-9]+:([0-9a-f]+)$`) // firstTag returns the hash and tag of the most recent tag matching re. func firstTag(re *regexp.Regexp) (hash string, tag string, err os.Error) { o, _, err := runLog(nil, "", goroot, "hg", "tags") - for _, l := range strings.Split(o, "\n", -1) { + for _, l := range strings.Split(o, "\n") { if l == "" { continue } diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 6b930f151ef..a4d83f1e7fe 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -66,7 +66,7 @@ func cname(s string) string { // preamble. Multiple occurrences are concatenated with a separating space, // even across files. func (p *Package) ParseFlags(f *File, srcfile string) { - linesIn := strings.Split(f.Preamble, "\n", -1) + linesIn := strings.Split(f.Preamble, "\n") linesOut := make([]string, 0, len(linesIn)) NextLine: @@ -78,7 +78,7 @@ NextLine: } l = strings.TrimSpace(l[4:]) - fields := strings.Split(l, ":", 2) + fields := strings.SplitN(l, ":", 2) if len(fields) != 2 { fatalf("%s: bad #cgo line: %s", srcfile, line) } @@ -275,7 +275,7 @@ func (p *Package) loadDefines(f *File) { b.WriteString(f.Preamble) stdout := p.gccDefines(b.Bytes()) - for _, line := range strings.Split(stdout, "\n", -1) { + for _, line := range strings.Split(stdout, "\n") { if len(line) < 9 || line[0:7] != "#define" { continue } @@ -397,7 +397,7 @@ func (p *Package) guessKinds(f *File) []*Name { isConst[i] = true // until proven otherwise } - for _, line := range strings.Split(stderr, "\n", -1) { + for _, line := range strings.Split(stderr, "\n") { if len(line) < 9 || line[0:9] != "cgo-test:" { // the user will see any compiler errors when the code is compiled later. continue @@ -1188,7 +1188,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { if ss, ok := dwarfToName[s]; ok { s = ss } - s = strings.Join(strings.Split(s, " ", -1), "") // strip spaces + s = strings.Join(strings.Split(s, " "), "") // strip spaces name := c.Ident("_Ctype_" + s) typedef[name.Name] = t.Go t.Go = name diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 7eecb3437fc..6802dd1cf33 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -148,7 +148,7 @@ func dynimport(obj string) { fatalf("cannot load imported symbols from PE file %s: %v", obj, err) } for _, s := range sym { - ss := strings.Split(s, ":", -1) + ss := strings.Split(s, ":") fmt.Printf("#pragma dynimport %s %s %q\n", ss[0], ss[0], strings.ToLower(ss[1])) } return diff --git a/src/cmd/godoc/dirtrees.go b/src/cmd/godoc/dirtrees.go index af44fa16ad5..ec969b74a4f 100644 --- a/src/cmd/godoc/dirtrees.go +++ b/src/cmd/godoc/dirtrees.go @@ -267,8 +267,8 @@ func (dir *Directory) lookupLocal(name string) *Directory { // lookup looks for the *Directory for a given path, relative to dir. func (dir *Directory) lookup(path string) *Directory { - d := strings.Split(dir.Path, string(filepath.Separator), -1) - p := strings.Split(path, string(filepath.Separator), -1) + d := strings.Split(dir.Path, string(filepath.Separator)) + p := strings.Split(path, string(filepath.Separator)) i := 0 for i < len(d) { if i >= len(p) || d[i] != p[i] { diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go index 30f18e88209..8209781225a 100644 --- a/src/cmd/godoc/godoc.go +++ b/src/cmd/godoc/godoc.go @@ -160,7 +160,7 @@ func readDirList(filename string) ([]string, os.Error) { } return e == nil && isPkgDir(d) } - list := canonicalizePaths(strings.Split(string(contents), "\n", -1), filter) + list := canonicalizePaths(strings.Split(string(contents), "\n"), filter) // for each parent path, remove all it's children q // (requirement for binary search to work when filtering) i := 0 diff --git a/src/cmd/godoc/index.go b/src/cmd/godoc/index.go index 61caee101da..91bd905d8ef 100644 --- a/src/cmd/godoc/index.go +++ b/src/cmd/godoc/index.go @@ -901,7 +901,7 @@ func isIdentifier(s string) bool { // identifier, Lookup returns a LookupResult, and a list of alternative // spellings, if any. If the query syntax is wrong, an error is reported. func (x *Index) Lookup(query string) (match *LookupResult, alt *AltWords, err os.Error) { - ss := strings.Split(query, ".", -1) + ss := strings.Split(query, ".") // check query syntax for _, s := range ss { diff --git a/src/cmd/gofix/Makefile b/src/cmd/gofix/Makefile index bce22121e0b..02d7463078b 100644 --- a/src/cmd/gofix/Makefile +++ b/src/cmd/gofix/Makefile @@ -19,6 +19,7 @@ GOFILES=\ procattr.go\ reflect.go\ sortslice.go\ + stringssplit.go\ typecheck.go\ include ../../Make.cmd diff --git a/src/cmd/gofix/main.go b/src/cmd/gofix/main.go index 05495bc0d82..e7e7013c568 100644 --- a/src/cmd/gofix/main.go +++ b/src/cmd/gofix/main.go @@ -53,7 +53,7 @@ func main() { if *allowedRewrites != "" { allowed = make(map[string]bool) - for _, f := range strings.Split(*allowedRewrites, ",", -1) { + for _, f := range strings.Split(*allowedRewrites, ",") { allowed[f] = true } } diff --git a/src/cmd/gofix/stringssplit.go b/src/cmd/gofix/stringssplit.go new file mode 100644 index 00000000000..4a1fe93d39a --- /dev/null +++ b/src/cmd/gofix/stringssplit.go @@ -0,0 +1,71 @@ +// Copyright 2011 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 main + +import ( + "go/ast" + "go/token" +) + +var stringssplitFix = fix{ + "stringssplit", + stringssplit, + `Restore strings.Split to its original meaning and add strings.SplitN. Bytes too. + +http://codereview.appspot.com/4661051 +`, +} + +func init() { + register(stringssplitFix) +} + +func stringssplit(f *ast.File) bool { + if !imports(f, "bytes") && !imports(f, "strings") { + return false + } + + fixed := false + walk(f, func(n interface{}) { + call, ok := n.(*ast.CallExpr) + // func Split(s, sep string, n int) []string + // func SplitAfter(s, sep string, n int) []string + if !ok || len(call.Args) != 3 { + return + } + // Is this our function? + switch { + case isPkgDot(call.Fun, "bytes", "Split"): + case isPkgDot(call.Fun, "bytes", "SplitAfter"): + case isPkgDot(call.Fun, "strings", "Split"): + case isPkgDot(call.Fun, "strings", "SplitAfter"): + default: + return + } + + sel := call.Fun.(*ast.SelectorExpr) + args := call.Args + fixed = true // We're committed. + + // Is the last argument -1? If so, drop the arg. + // (Actually we just look for a negative integer literal.) + // Otherwise, Split->SplitN and keep the arg. + final := args[2] + if unary, ok := final.(*ast.UnaryExpr); ok && unary.Op == token.SUB { + if lit, ok := unary.X.(*ast.BasicLit); ok { + // Is it an integer? If so, it's a negative integer and that's what we're after. + if lit.Kind == token.INT { + // drop the last arg. + call.Args = args[0:2] + return + } + } + } + + // If not, rename and keep the argument list. + sel.Sel.Name += "N" + }) + return fixed +} diff --git a/src/cmd/gofix/stringssplit_test.go b/src/cmd/gofix/stringssplit_test.go new file mode 100644 index 00000000000..b925722af79 --- /dev/null +++ b/src/cmd/gofix/stringssplit_test.go @@ -0,0 +1,51 @@ +// Copyright 2011 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 main + +func init() { + addTestCases(stringssplitTests) +} + +var stringssplitTests = []testCase{ + { + Name: "stringssplit.0", + In: `package main + +import ( + "bytes" + "strings" +) + +func f() { + bytes.Split(a, b, c) + bytes.Split(a, b, -1) + bytes.SplitAfter(a, b, c) + bytes.SplitAfter(a, b, -1) + strings.Split(a, b, c) + strings.Split(a, b, -1) + strings.SplitAfter(a, b, c) + strings.SplitAfter(a, b, -1) +} +`, + Out: `package main + +import ( + "bytes" + "strings" +) + +func f() { + bytes.SplitN(a, b, c) + bytes.Split(a, b) + bytes.SplitAfterN(a, b, c) + bytes.SplitAfter(a, b) + strings.SplitN(a, b, c) + strings.Split(a, b) + strings.SplitAfterN(a, b, c) + strings.SplitAfter(a, b) +} +`, + }, +} diff --git a/src/cmd/gofix/testdata/reflect.template.go.in b/src/cmd/gofix/testdata/reflect.template.go.in index ba06de4e3ab..1f5a8128fdd 100644 --- a/src/cmd/gofix/testdata/reflect.template.go.in +++ b/src/cmd/gofix/testdata/reflect.template.go.in @@ -444,7 +444,7 @@ func (t *Template) newVariable(words []string) *variableElement { bar := strings.IndexRune(lastWord, '|') if bar >= 0 { words[len(words)-1] = lastWord[0:bar] - formatters = strings.Split(lastWord[bar+1:], "|", -1) + formatters = strings.Split(lastWord[bar+1:], "|") } // We could remember the function address here and avoid the lookup later, @@ -705,7 +705,7 @@ func (t *Template) findVar(st *state, s string) reflect.Value { if s == "@" { return indirectPtr(data, numStars) } - for _, elem := range strings.Split(s, ".", -1) { + for _, elem := range strings.Split(s, ".") { // Look up field; data must be a struct or map. data = t.lookup(st, data, elem) if data == nil { diff --git a/src/cmd/gofix/testdata/reflect.template.go.out b/src/cmd/gofix/testdata/reflect.template.go.out index c3628845593..f2f56ef3c29 100644 --- a/src/cmd/gofix/testdata/reflect.template.go.out +++ b/src/cmd/gofix/testdata/reflect.template.go.out @@ -444,7 +444,7 @@ func (t *Template) newVariable(words []string) *variableElement { bar := strings.IndexRune(lastWord, '|') if bar >= 0 { words[len(words)-1] = lastWord[0:bar] - formatters = strings.Split(lastWord[bar+1:], "|", -1) + formatters = strings.Split(lastWord[bar+1:], "|") } // We could remember the function address here and avoid the lookup later, @@ -705,7 +705,7 @@ func (t *Template) findVar(st *state, s string) reflect.Value { if s == "@" { return indirectPtr(data, numStars) } - for _, elem := range strings.Split(s, ".", -1) { + for _, elem := range strings.Split(s, ".") { // Look up field; data must be a struct or map. data = t.lookup(st, data, elem) if !data.IsValid() { diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go index a72530307ee..70700554ba7 100644 --- a/src/cmd/gofmt/gofmt_test.go +++ b/src/cmd/gofmt/gofmt_test.go @@ -20,8 +20,8 @@ func runTest(t *testing.T, dirname, in, out, flags string) { // process flags *simplifyAST = false *rewriteRule = "" - for _, flag := range strings.Split(flags, " ", -1) { - elts := strings.Split(flag, "=", 2) + for _, flag := range strings.Split(flags, " ") { + elts := strings.SplitN(flag, "=", 2) name := elts[0] value := "" if len(elts) == 2 { diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go index 4c24282f369..f7f1fe82435 100644 --- a/src/cmd/gofmt/rewrite.go +++ b/src/cmd/gofmt/rewrite.go @@ -22,7 +22,7 @@ func initRewrite() { rewrite = nil // disable any previous rewrite return } - f := strings.Split(*rewriteRule, "->", -1) + f := strings.Split(*rewriteRule, "->") if len(f) != 2 { fmt.Fprintf(os.Stderr, "rewrite rule must be of the form 'pattern -> replacement'\n") os.Exit(2) diff --git a/src/cmd/goinstall/download.go b/src/cmd/goinstall/download.go index d209fa82bf3..129c0459a6b 100644 --- a/src/cmd/goinstall/download.go +++ b/src/cmd/goinstall/download.go @@ -146,11 +146,11 @@ var vcsList = []*vcs{&git, &hg, &bzr, &svn} // hostname - i.e. contains at least one '.' and the last part is at least 2 // characters. func isRemote(pkg string) bool { - parts := strings.Split(pkg, "/", 2) + parts := strings.SplitN(pkg, "/", 2) if len(parts) != 2 { return false } - parts = strings.Split(parts[0], ".", -1) + parts = strings.Split(parts[0], ".") if len(parts) < 2 || len(parts[len(parts)-1]) < 2 { return false } diff --git a/src/cmd/govet/govet.go b/src/cmd/govet/govet.go index b811c61a2d9..73bd2faeffa 100644 --- a/src/cmd/govet/govet.go +++ b/src/cmd/govet/govet.go @@ -50,7 +50,7 @@ func main() { flag.Parse() if *printfuncs != "" { - for _, name := range strings.Split(*printfuncs, ",", -1) { + for _, name := range strings.Split(*printfuncs, ",") { if len(name) == 0 { flag.Usage() } diff --git a/src/cmd/goyacc/goyacc.go b/src/cmd/goyacc/goyacc.go index 220c9949202..543f8b1e862 100644 --- a/src/cmd/goyacc/goyacc.go +++ b/src/cmd/goyacc/goyacc.go @@ -2834,7 +2834,7 @@ func others() { // copy yaccpar fmt.Fprintf(ftable, "\n//line yaccpar:1\n") - parts := strings.Split(yaccpar, prefix+"run()", 2) + parts := strings.SplitN(yaccpar, prefix+"run()", 2) fmt.Fprintf(ftable, "%v", parts[0]) ftable.Write(fcode.Bytes()) fmt.Fprintf(ftable, "%v", parts[1]) diff --git a/src/cmd/hgpatch/main.go b/src/cmd/hgpatch/main.go index 1f3e5e73652..6a197bd54b5 100644 --- a/src/cmd/hgpatch/main.go +++ b/src/cmd/hgpatch/main.go @@ -282,7 +282,7 @@ func hgModified() ([]string, os.Error) { if err != nil { return nil, err } - return strings.Split(strings.TrimSpace(out), "\n", -1), nil + return strings.Split(strings.TrimSpace(out), "\n"), nil } // hgAdd adds name to the repository. diff --git a/src/pkg/asn1/common.go b/src/pkg/asn1/common.go index 9db887e251b..854f4da4808 100644 --- a/src/pkg/asn1/common.go +++ b/src/pkg/asn1/common.go @@ -83,7 +83,7 @@ type fieldParameters struct { // parseFieldParameters will parse it into a fieldParameters structure, // ignoring unknown parts of the string. func parseFieldParameters(str string) (ret fieldParameters) { - for _, part := range strings.Split(str, ",", -1) { + for _, part := range strings.Split(str, ",") { switch { case part == "optional": ret.optional = true diff --git a/src/pkg/bytes/bytes.go b/src/pkg/bytes/bytes.go index 0f9ac986371..3cec60f96c9 100644 --- a/src/pkg/bytes/bytes.go +++ b/src/pkg/bytes/bytes.go @@ -212,24 +212,38 @@ func genSplit(s, sep []byte, sepSave, n int) [][]byte { return a[0 : na+1] } -// Split slices s into subslices separated by sep and returns a slice of +// SplitN slices s into subslices separated by sep and returns a slice of +// the subslices between those separators. +// If sep is empty, SplitN splits after each UTF-8 sequence. +// The count determines the number of subslices to return: +// n > 0: at most n subslices; the last subslice will be the unsplit remainder. +// n == 0: the result is nil (zero subslices) +// n < 0: all subslices +func SplitN(s, sep []byte, n int) [][]byte { return genSplit(s, sep, 0, n) } + +// SplitAfterN slices s into subslices after each instance of sep and +// returns a slice of those subslices. +// If sep is empty, SplitAfterN splits after each UTF-8 sequence. +// The count determines the number of subslices to return: +// n > 0: at most n subslices; the last subslice will be the unsplit remainder. +// n == 0: the result is nil (zero subslices) +// n < 0: all subslices +func SplitAfterN(s, sep []byte, n int) [][]byte { + return genSplit(s, sep, len(sep), n) +} + +// Split slices s into all subslices separated by sep and returns a slice of // the subslices between those separators. // If sep is empty, Split splits after each UTF-8 sequence. -// The count determines the number of subslices to return: -// n > 0: at most n subslices; the last subslice will be the unsplit remainder. -// n == 0: the result is nil (zero subslices) -// n < 0: all subslices -func Split(s, sep []byte, n int) [][]byte { return genSplit(s, sep, 0, n) } +// It is equivalent to SplitN with a count of -1. +func Split(s, sep []byte) [][]byte { return genSplit(s, sep, 0, -1) } -// SplitAfter slices s into subslices after each instance of sep and +// SplitAfter slices s into all subslices after each instance of sep and // returns a slice of those subslices. -// If sep is empty, Split splits after each UTF-8 sequence. -// The count determines the number of subslices to return: -// n > 0: at most n subslices; the last subslice will be the unsplit remainder. -// n == 0: the result is nil (zero subslices) -// n < 0: all subslices -func SplitAfter(s, sep []byte, n int) [][]byte { - return genSplit(s, sep, len(sep), n) +// If sep is empty, SplitAfter splits after each UTF-8 sequence. +// It is equivalent to SplitAfterN with a count of -1. +func SplitAfter(s, sep []byte) [][]byte { + return genSplit(s, sep, len(sep), -1) } // Fields splits the array s around each instance of one or more consecutive white space diff --git a/src/pkg/bytes/bytes_test.go b/src/pkg/bytes/bytes_test.go index 4ce291a4f67..75393530918 100644 --- a/src/pkg/bytes/bytes_test.go +++ b/src/pkg/bytes/bytes_test.go @@ -6,6 +6,7 @@ package bytes_test import ( . "bytes" + "reflect" "testing" "unicode" "utf8" @@ -315,7 +316,7 @@ var explodetests = []ExplodeTest{ func TestExplode(t *testing.T) { for _, tt := range explodetests { - a := Split([]byte(tt.s), nil, tt.n) + a := SplitN([]byte(tt.s), nil, tt.n) result := arrayOfString(a) if !eq(result, tt.a) { t.Errorf(`Explode("%s", %d) = %v; want %v`, tt.s, tt.n, result, tt.a) @@ -354,7 +355,7 @@ var splittests = []SplitTest{ func TestSplit(t *testing.T) { for _, tt := range splittests { - a := Split([]byte(tt.s), []byte(tt.sep), tt.n) + a := SplitN([]byte(tt.s), []byte(tt.sep), tt.n) result := arrayOfString(a) if !eq(result, tt.a) { t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a) @@ -367,6 +368,12 @@ func TestSplit(t *testing.T) { if string(s) != tt.s { t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s) } + if tt.n < 0 { + b := Split([]byte(tt.s), []byte(tt.sep)) + if !reflect.DeepEqual(a, b) { + t.Errorf("Split disagrees withSplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) + } + } } } @@ -388,7 +395,7 @@ var splitaftertests = []SplitTest{ func TestSplitAfter(t *testing.T) { for _, tt := range splitaftertests { - a := SplitAfter([]byte(tt.s), []byte(tt.sep), tt.n) + a := SplitAfterN([]byte(tt.s), []byte(tt.sep), tt.n) result := arrayOfString(a) if !eq(result, tt.a) { t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a) @@ -398,6 +405,12 @@ func TestSplitAfter(t *testing.T) { if string(s) != tt.s { t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s) } + if tt.n < 0 { + b := SplitAfter([]byte(tt.s), []byte(tt.sep)) + if !reflect.DeepEqual(a, b) { + t.Errorf("SplitAfter disagrees withSplitAfterN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) + } + } } } diff --git a/src/pkg/compress/lzw/reader_test.go b/src/pkg/compress/lzw/reader_test.go index 72121a6b569..f8042b0d191 100644 --- a/src/pkg/compress/lzw/reader_test.go +++ b/src/pkg/compress/lzw/reader_test.go @@ -84,7 +84,7 @@ var lzwTests = []lzwTest{ func TestReader(t *testing.T) { b := bytes.NewBuffer(nil) for _, tt := range lzwTests { - d := strings.Split(tt.desc, ";", -1) + d := strings.Split(tt.desc, ";") var order Order switch d[1] { case "LSB": diff --git a/src/pkg/crypto/x509/verify.go b/src/pkg/crypto/x509/verify.go index 9145880a237..20a81574d0a 100644 --- a/src/pkg/crypto/x509/verify.go +++ b/src/pkg/crypto/x509/verify.go @@ -202,8 +202,8 @@ func matchHostnames(pattern, host string) bool { return false } - patternParts := strings.Split(pattern, ".", -1) - hostParts := strings.Split(host, ".", -1) + patternParts := strings.Split(pattern, ".") + hostParts := strings.Split(host, ".") if len(patternParts) != len(hostParts) { return false diff --git a/src/pkg/debug/proc/proc_linux.go b/src/pkg/debug/proc/proc_linux.go index 5831b0e9795..7ec797114c4 100644 --- a/src/pkg/debug/proc/proc_linux.go +++ b/src/pkg/debug/proc/proc_linux.go @@ -1229,7 +1229,7 @@ func (p *process) attachAllThreads() os.Error { return err } - statParts := strings.Split(string(statFile), " ", 4) + statParts := strings.SplitN(string(statFile), " ", 4) if len(statParts) > 2 && statParts[2] == "Z" { // tid is a zombie p.logTrace("thread %d is a zombie", tid) diff --git a/src/pkg/exec/exec_test.go b/src/pkg/exec/exec_test.go index c45a7d70a65..f6cebb90553 100644 --- a/src/pkg/exec/exec_test.go +++ b/src/pkg/exec/exec_test.go @@ -55,7 +55,7 @@ func TestCatGoodAndBadFile(t *testing.T) { t.Errorf("expected Waitmsg from cat combined; got %T: %v", err, err) } s := string(bs) - sp := strings.Split(s, "\n", 2) + sp := strings.SplitN(s, "\n", 2) if len(sp) != 2 { t.Fatalf("expected two lines from cat; got %q", s) } diff --git a/src/pkg/exec/lp_plan9.go b/src/pkg/exec/lp_plan9.go index c4e2a7a0f93..e4751a4df29 100644 --- a/src/pkg/exec/lp_plan9.go +++ b/src/pkg/exec/lp_plan9.go @@ -42,7 +42,7 @@ func LookPath(file string) (string, os.Error) { } path := os.Getenv("path") - for _, dir := range strings.Split(path, "\000", -1) { + for _, dir := range strings.Split(path, "\000") { if err := findExecutable(dir + "/" + file); err == nil { return dir + "/" + file, nil } diff --git a/src/pkg/exec/lp_unix.go b/src/pkg/exec/lp_unix.go index cdf7207688c..008fb11a81c 100644 --- a/src/pkg/exec/lp_unix.go +++ b/src/pkg/exec/lp_unix.go @@ -39,7 +39,7 @@ func LookPath(file string) (string, os.Error) { return "", &Error{file, err} } pathenv := os.Getenv("PATH") - for _, dir := range strings.Split(pathenv, ":", -1) { + for _, dir := range strings.Split(pathenv, ":") { if dir == "" { // Unix shell semantics: path element "" means "." dir = "." diff --git a/src/pkg/exec/lp_windows.go b/src/pkg/exec/lp_windows.go index 47763458f81..7581088eb09 100644 --- a/src/pkg/exec/lp_windows.go +++ b/src/pkg/exec/lp_windows.go @@ -47,7 +47,7 @@ func LookPath(file string) (f string, err os.Error) { x = `.COM;.EXE;.BAT;.CMD` } exts := []string{} - for _, e := range strings.Split(strings.ToLower(x), `;`, -1) { + for _, e := range strings.Split(strings.ToLower(x), `;`) { if e == "" { continue } @@ -67,7 +67,7 @@ func LookPath(file string) (f string, err os.Error) { return } } else { - for _, dir := range strings.Split(pathenv, `;`, -1) { + for _, dir := range strings.Split(pathenv, `;`) { if f, err = findExecutable(dir+`\`+file, exts); err == nil { return } diff --git a/src/pkg/exp/ogle/cmd.go b/src/pkg/exp/ogle/cmd.go index a8db523ea18..ff0d24c692f 100644 --- a/src/pkg/exp/ogle/cmd.go +++ b/src/pkg/exp/ogle/cmd.go @@ -154,7 +154,7 @@ func cmdLoad(args []byte) os.Error { } println("Attached to", pid) } else { - parts := strings.Split(path, " ", -1) + parts := strings.Split(path, " ") if len(parts) == 0 { fname = "" } else { diff --git a/src/pkg/go/ast/print_test.go b/src/pkg/go/ast/print_test.go index 0820dcfcef2..30b396fcf65 100644 --- a/src/pkg/go/ast/print_test.go +++ b/src/pkg/go/ast/print_test.go @@ -53,7 +53,7 @@ var tests = []struct { // Split s into lines, trim whitespace from all lines, and return // the concatenated non-empty lines. func trim(s string) string { - lines := strings.Split(s, "\n", -1) + lines := strings.Split(s, "\n") i := 0 for _, line := range lines { line = strings.TrimSpace(line) diff --git a/src/pkg/go/build/dir.go b/src/pkg/go/build/dir.go index 20f8f2913f8..e0000b53446 100644 --- a/src/pkg/go/build/dir.go +++ b/src/pkg/go/build/dir.go @@ -139,7 +139,7 @@ func goodOSArch(filename string) bool { if dot := strings.Index(filename, "."); dot != -1 { filename = filename[:dot] } - l := strings.Split(filename, "_", -1) + l := strings.Split(filename, "_") n := len(l) if n == 0 { return true diff --git a/src/pkg/go/doc/comment.go b/src/pkg/go/doc/comment.go index f1ebfa97b9f..85640af796e 100644 --- a/src/pkg/go/doc/comment.go +++ b/src/pkg/go/doc/comment.go @@ -58,7 +58,7 @@ func CommentText(comment *ast.CommentGroup) string { } // Split on newlines. - cl := strings.Split(c, "\n", -1) + cl := strings.Split(c, "\n") // Walk lines, stripping trailing white space and adding to list. for _, l := range cl { diff --git a/src/pkg/html/token_test.go b/src/pkg/html/token_test.go index c17b436aab4..c794612abcf 100644 --- a/src/pkg/html/token_test.go +++ b/src/pkg/html/token_test.go @@ -161,7 +161,7 @@ func TestTokenizer(t *testing.T) { loop: for _, tt := range tokenTests { z := NewTokenizer(bytes.NewBuffer([]byte(tt.html))) - for i, s := range strings.Split(tt.golden, "$", -1) { + for i, s := range strings.Split(tt.golden, "$") { if z.Next() == ErrorToken { t.Errorf("%s token %d: want %q got error %v", tt.desc, i, s, z.Error()) continue loop diff --git a/src/pkg/http/cgi/host.go b/src/pkg/http/cgi/host.go index 2be3ede774a..01a941650bd 100644 --- a/src/pkg/http/cgi/host.go +++ b/src/pkg/http/cgi/host.go @@ -197,7 +197,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if len(line) == 0 { break } - parts := strings.Split(string(line), ":", 2) + parts := strings.SplitN(string(line), ":", 2) if len(parts) < 2 { h.printf("cgi: bogus header line: %s", string(line)) continue diff --git a/src/pkg/http/cgi/host_test.go b/src/pkg/http/cgi/host_test.go index bbdb715cf91..3b9dad5c0c5 100644 --- a/src/pkg/http/cgi/host_test.go +++ b/src/pkg/http/cgi/host_test.go @@ -46,7 +46,7 @@ readlines: } linesRead++ trimmedLine := strings.TrimRight(line, "\r\n") - split := strings.Split(trimmedLine, "=", 2) + split := strings.SplitN(trimmedLine, "=", 2) if len(split) != 2 { t.Fatalf("Unexpected %d parts from invalid line number %v: %q; existing map=%v", len(split), linesRead, line, m) diff --git a/src/pkg/http/cookie.go b/src/pkg/http/cookie.go index 79c239b46e7..fe70431bbbc 100644 --- a/src/pkg/http/cookie.go +++ b/src/pkg/http/cookie.go @@ -41,7 +41,7 @@ type Cookie struct { func readSetCookies(h Header) []*Cookie { cookies := []*Cookie{} for _, line := range h["Set-Cookie"] { - parts := strings.Split(strings.TrimSpace(line), ";", -1) + parts := strings.Split(strings.TrimSpace(line), ";") if len(parts) == 1 && parts[0] == "" { continue } @@ -175,7 +175,7 @@ func readCookies(h Header, filter string) []*Cookie { } for _, line := range lines { - parts := strings.Split(strings.TrimSpace(line), ";", -1) + parts := strings.Split(strings.TrimSpace(line), ";") if len(parts) == 1 && parts[0] == "" { continue } diff --git a/src/pkg/http/fs.go b/src/pkg/http/fs.go index 139fe2cb0f4..0b830053a9b 100644 --- a/src/pkg/http/fs.go +++ b/src/pkg/http/fs.go @@ -259,7 +259,7 @@ func parseRange(s string, size int64) ([]httpRange, os.Error) { return nil, os.NewError("invalid range") } var ranges []httpRange - for _, ra := range strings.Split(s[len(b):], ",", -1) { + for _, ra := range strings.Split(s[len(b):], ",") { i := strings.Index(ra, "-") if i < 0 { return nil, os.NewError("invalid range") diff --git a/src/pkg/http/request.go b/src/pkg/http/request.go index cd6965fa5db..456476a2129 100644 --- a/src/pkg/http/request.go +++ b/src/pkg/http/request.go @@ -543,7 +543,7 @@ func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) { } var f []string - if f = strings.Split(s, " ", 3); len(f) < 3 { + if f = strings.SplitN(s, " ", 3); len(f) < 3 { return nil, &badStringError{"malformed HTTP request", s} } req.Method, req.RawURL, req.Proto = f[0], f[1], f[2] @@ -662,11 +662,11 @@ func ParseQuery(query string) (m Values, err os.Error) { } func parseQuery(m Values, query string) (err os.Error) { - for _, kv := range strings.Split(query, "&", -1) { + for _, kv := range strings.Split(query, "&") { if len(kv) == 0 { continue } - kvPair := strings.Split(kv, "=", 2) + kvPair := strings.SplitN(kv, "=", 2) var key, value string var e os.Error @@ -703,7 +703,7 @@ func (r *Request) ParseForm() (err os.Error) { return os.NewError("missing form body") } ct := r.Header.Get("Content-Type") - switch strings.Split(ct, ";", 2)[0] { + switch strings.SplitN(ct, ";", 2)[0] { case "text/plain", "application/x-www-form-urlencoded", "": const maxFormSize = int64(10 << 20) // 10 MB is a lot of text. b, e := ioutil.ReadAll(io.LimitReader(r.Body, maxFormSize+1)) diff --git a/src/pkg/http/response.go b/src/pkg/http/response.go index 6c0c441a944..915327a69ec 100644 --- a/src/pkg/http/response.go +++ b/src/pkg/http/response.go @@ -95,7 +95,7 @@ func ReadResponse(r *bufio.Reader, req *Request) (resp *Response, err os.Error) } return nil, err } - f := strings.Split(line, " ", 3) + f := strings.SplitN(line, " ", 3) if len(f) < 2 { return nil, &badStringError{"malformed HTTP response", line} } diff --git a/src/pkg/http/server.go b/src/pkg/http/server.go index 08cbed7ad87..ab960f4f0a8 100644 --- a/src/pkg/http/server.go +++ b/src/pkg/http/server.go @@ -421,7 +421,7 @@ func errorKludge(w *response) { msg += " would ignore this error page if this text weren't here.\n" // Is it text? ("Content-Type" is always in the map) - baseType := strings.Split(w.header.Get("Content-Type"), ";", 2)[0] + baseType := strings.SplitN(w.header.Get("Content-Type"), ";", 2)[0] switch baseType { case "text/html": io.WriteString(w, "