diff options
Diffstat (limited to 'src/lib/strings')
-rw-r--r-- | src/lib/strings/Makefile | 68 | ||||
-rw-r--r-- | src/lib/strings/strings.go | 119 | ||||
-rw-r--r-- | src/lib/strings/strings_test.go | 81 |
3 files changed, 268 insertions, 0 deletions
diff --git a/src/lib/strings/Makefile b/src/lib/strings/Makefile new file mode 100644 index 000000000..9372f4d16 --- /dev/null +++ b/src/lib/strings/Makefile @@ -0,0 +1,68 @@ +# Copyright 2009 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. + +# DO NOT EDIT. Automatically generated by gobuild. +# gobuild -m >Makefile + +D= + +O_arm=5 +O_amd64=6 +O_386=8 +OS=568vq + +O=$(O_$(GOARCH)) +GC=$(O)g -I_obj +CC=$(O)c -FVw +AS=$(O)a +AR=6ar + +default: packages + +clean: + rm -rf *.[$(OS)] *.a [$(OS)].out _obj + +test: packages + gotest + +coverage: packages + gotest + 6cov -g `pwd` | grep -v '_test\.go:' + +%.$O: %.go + $(GC) $*.go + +%.$O: %.c + $(CC) $*.c + +%.$O: %.s + $(AS) $*.s + +O1=\ + strings.$O\ + + +phases: a1 +_obj$D/strings.a: phases + +a1: $(O1) + $(AR) grc _obj$D/strings.a strings.$O + rm -f $(O1) + + +newpkg: clean + mkdir -p _obj$D + $(AR) grc _obj$D/strings.a + +$(O1): newpkg +$(O2): a1 + +nuke: clean + rm -f $(GOROOT)/pkg$D/strings.a + +packages: _obj$D/strings.a + +install: packages + test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg$D + cp _obj$D/strings.a $(GOROOT)/pkg$D/strings.a diff --git a/src/lib/strings/strings.go b/src/lib/strings/strings.go new file mode 100644 index 000000000..33adab249 --- /dev/null +++ b/src/lib/strings/strings.go @@ -0,0 +1,119 @@ +// Copyright 2009 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. + +// A package of simple functions to manipulate strings. +package strings + +import "utf8" + +// Explode splits s into an array of UTF-8 sequences, one per Unicode character (still strings). +// Invalid UTF-8 sequences become correct encodings of U+FFF8. +func Explode(s string) []string { + a := make([]string, utf8.RuneCountInString(s)); + j := 0; + var size, rune int; + for i := 0; i < len(a); i++ { + rune, size = utf8.DecodeRuneInString(s, j); + a[i] = string(rune); + j += size; + } + return a +} + +// Count counts the number of non-overlapping instances of sep in s. +func Count(s, sep string) int { + if sep == "" { + return utf8.RuneCountInString(s)+1 + } + c := sep[0]; + n := 0; + for i := 0; i+len(sep) <= len(s); i++ { + if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) { + n++; + i += len(sep)-1 + } + } + return n +} + +// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. +func Index(s, sep string) int { + n := len(sep); + if n == 0 { + return 0 + } + c := sep[0]; + for i := 0; i+n <= len(s); i++ { + if s[i] == c && (n == 1 || s[i:i+n] == sep) { + return i + } + } + return -1 +} + +// Split returns the array representing the substrings of s separated by string sep. Adjacent +// occurrences of sep produce empty substrings. If sep is empty, it is the same as Explode. +func Split(s, sep string) []string { + if sep == "" { + return Explode(s) + } + c := sep[0]; + start := 0; + n := Count(s, sep)+1; + a := make([]string, n); + na := 0; + for i := 0; i+len(sep) <= len(s); i++ { + if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) { + a[na] = s[start:i]; + na++; + start = i+len(sep); + i += len(sep)-1 + } + } + a[na] = s[start:len(s)]; + return a +} + +// Join concatenates the elements of a to create a single string. The separator string +// sep is placed between elements in the resulting string. +func Join(a []string, sep string) string { + if len(a) == 0 { + return "" + } + if len(a) == 1 { + return a[0] + } + n := len(sep) * (len(a)-1); + for i := 0; i < len(a); i++ { + n += len(a[i]) + } + + b := make([]byte, n); + bp := 0; + for i := 0; i < len(a); i++ { + s := a[i]; + for j := 0; j < len(s); j++ { + b[bp] = s[j]; + bp++ + } + if i + 1 < len(a) { + s = sep; + for j := 0; j < len(s); j++ { + b[bp] = s[j]; + bp++ + } + } + } + return string(b) +} + +// HasPrefix tests whether the string s begins with prefix. +func HasPrefix(s, prefix string) bool { + return len(s) >= len(prefix) && s[0:len(prefix)] == prefix +} + +// HasSuffix tests whether the string s ends with suffix. +func HasSuffix(s, suffix string) bool { + return len(s) >= len(suffix) && s[len(s)-len(suffix):len(s)] == suffix +} diff --git a/src/lib/strings/strings_test.go b/src/lib/strings/strings_test.go new file mode 100644 index 000000000..2cbf70b93 --- /dev/null +++ b/src/lib/strings/strings_test.go @@ -0,0 +1,81 @@ +// Copyright 2009 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 strings + +import ( + "strings"; + "testing"; +) + +func eq(a, b []string) bool { + if len(a) != len(b) { + return false; + } + for i := 0; i < len(a); i++ { + if a[i] != b[i] { + return false; + } + } + return true; +} + +var abcd = "abcd"; +var faces = "☺☻☹"; +var commas = "1,2,3,4"; +var dots = "1....2....3....4"; + +type ExplodeTest struct { + s string; + a []string; +} +var explodetests = []ExplodeTest { + ExplodeTest{ abcd, []string{"a", "b", "c", "d"} }, + ExplodeTest{ faces, []string{"☺", "☻", "☹" } }, +} +func TestExplode(t *testing.T) { + for i := 0; i < len(explodetests); i++ { + tt := explodetests[i]; + a := Explode(tt.s); + if !eq(a, tt.a) { + t.Errorf("Explode(%q) = %v; want %v", tt.s, a, tt.a); + continue; + } + s := Join(a, ""); + if s != tt.s { + t.Errorf(`Join(Explode(%q), "") = %q`, tt.s, s); + } + } +} + +type SplitTest struct { + s string; + sep string; + a []string; +} +var splittests = []SplitTest { + SplitTest{ abcd, "a", []string{"", "bcd"} }, + SplitTest{ abcd, "z", []string{"abcd"} }, + SplitTest{ abcd, "", []string{"a", "b", "c", "d"} }, + SplitTest{ commas, ",", []string{"1", "2", "3", "4"} }, + SplitTest{ dots, "...", []string{"1", ".2", ".3", ".4"} }, + SplitTest{ faces, "☹", []string{"☺☻", ""} }, + SplitTest{ faces, "~", []string{faces} }, + SplitTest{ faces, "", []string{"☺", "☻", "☹"} }, +} +func TestSplit(t *testing.T) { + for i := 0; i < len(splittests); i++ { + tt := splittests[i]; + a := Split(tt.s, tt.sep); + if !eq(a, tt.a) { + t.Errorf("Split(%q, %q) = %v; want %v", tt.s, tt.sep, a, tt.a); + continue; + } + s := Join(a, tt.sep); + if s != tt.s { + t.Errorf("Join(Split(%q, %q), %q) = %q", tt.s, tt.sep, tt.sep, s); + } + } +} + |