summaryrefslogtreecommitdiff
path: root/libgo/go/bytes
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-01-12 01:31:45 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-01-12 01:31:45 +0000
commit26ae0101ebafafea33beadccea3056f4b5e135e8 (patch)
tree86a3b8019380d5fad53258c4baba3dd9e1e7c736 /libgo/go/bytes
parentc8142b20a95ae9c6bd0bac8c5a545b27402836fe (diff)
downloadgcc-26ae0101ebafafea33beadccea3056f4b5e135e8.tar.gz
libgo: Update to weekly.2011-12-14.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183118 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/go/bytes')
-rw-r--r--libgo/go/bytes/bytes.go55
-rw-r--r--libgo/go/bytes/bytes_test.go147
-rw-r--r--libgo/go/bytes/export_test.go1
-rw-r--r--libgo/go/bytes/indexbyte.c14
4 files changed, 190 insertions, 27 deletions
diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go
index 9bfd88fa398..e94a0ec5c4f 100644
--- a/libgo/go/bytes/bytes.go
+++ b/libgo/go/bytes/bytes.go
@@ -37,7 +37,9 @@ func Compare(a, b []byte) int {
}
// Equal returns a boolean reporting whether a == b.
-func Equal(a, b []byte) bool {
+func Equal(a, b []byte) bool
+
+func equalPortable(a, b []byte) bool {
if len(a) != len(b) {
return false
}
@@ -74,18 +76,33 @@ func explode(s []byte, n int) [][]byte {
// Count counts the number of non-overlapping instances of sep in s.
func Count(s, sep []byte) int {
- if len(sep) == 0 {
+ n := len(sep)
+ if n == 0 {
return utf8.RuneCount(s) + 1
}
+ if n > len(s) {
+ return 0
+ }
+ count := 0
c := sep[0]
- n := 0
- for i := 0; i+len(sep) <= len(s); i++ {
- if s[i] == c && (len(sep) == 1 || Equal(s[i:i+len(sep)], sep)) {
- n++
- i += len(sep) - 1
+ i := 0
+ t := s[:len(s)-n+1]
+ for i < len(t) {
+ if t[i] != c {
+ o := IndexByte(t[i:], c)
+ if o < 0 {
+ break
+ }
+ i += o
}
+ if n == 1 || Equal(s[i:i+n], sep) {
+ count++
+ i += n
+ continue
+ }
+ i++
}
- return n
+ return count
}
// Contains returns whether subslice is within b.
@@ -99,11 +116,27 @@ func Index(s, sep []byte) int {
if n == 0 {
return 0
}
+ if n > len(s) {
+ return -1
+ }
c := sep[0]
- for i := 0; i+n <= len(s); i++ {
- if s[i] == c && (n == 1 || Equal(s[i:i+n], sep)) {
+ if n == 1 {
+ return IndexByte(s, c)
+ }
+ i := 0
+ t := s[:len(s)-n+1]
+ for i < len(t) {
+ if t[i] != c {
+ o := IndexByte(t[i:], c)
+ if o < 0 {
+ break
+ }
+ i += o
+ }
+ if Equal(s[i:i+n], sep) {
return i
}
+ i++
}
return -1
}
@@ -437,7 +470,7 @@ func Title(s []byte) []byte {
// Use a closure here to remember state.
// Hackish but effective. Depends on Map scanning in order and calling
// the closure once per rune.
- prev := rune(' ')
+ prev := ' '
return Map(
func(r rune) rune {
if isSeparator(prev) {
diff --git a/libgo/go/bytes/bytes_test.go b/libgo/go/bytes/bytes_test.go
index 829ef05319c..a2a08c20db0 100644
--- a/libgo/go/bytes/bytes_test.go
+++ b/libgo/go/bytes/bytes_test.go
@@ -64,13 +64,17 @@ func TestCompare(t *testing.T) {
a := []byte(tt.a)
b := []byte(tt.b)
cmp := Compare(a, b)
- eql := Equal(a, b)
if cmp != tt.i {
t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp)
}
+ eql := Equal(a, b)
if eql != (tt.i == 0) {
t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql)
}
+ eql = EqualPortable(a, b)
+ if eql != (tt.i == 0) {
+ t.Errorf(`EqualPortable(%q, %q) = %v`, tt.a, tt.b, eql)
+ }
}
}
@@ -264,41 +268,152 @@ func TestIndexRune(t *testing.T) {
}
}
-func BenchmarkIndexByte4K(b *testing.B) { bmIndex(b, IndexByte, 4<<10) }
-
-func BenchmarkIndexByte4M(b *testing.B) { bmIndex(b, IndexByte, 4<<20) }
+var bmbuf []byte
-func BenchmarkIndexByte64M(b *testing.B) { bmIndex(b, IndexByte, 64<<20) }
+func BenchmarkIndexByte32(b *testing.B) { bmIndexByte(b, IndexByte, 32) }
+func BenchmarkIndexByte4K(b *testing.B) { bmIndexByte(b, IndexByte, 4<<10) }
+func BenchmarkIndexByte4M(b *testing.B) { bmIndexByte(b, IndexByte, 4<<20) }
+func BenchmarkIndexByte64M(b *testing.B) { bmIndexByte(b, IndexByte, 64<<20) }
+func BenchmarkIndexBytePortable32(b *testing.B) { bmIndexByte(b, IndexBytePortable, 32) }
+func BenchmarkIndexBytePortable4K(b *testing.B) { bmIndexByte(b, IndexBytePortable, 4<<10) }
+func BenchmarkIndexBytePortable4M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 4<<20) }
+func BenchmarkIndexBytePortable64M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 64<<20) }
-func BenchmarkIndexBytePortable4K(b *testing.B) {
- bmIndex(b, IndexBytePortable, 4<<10)
+func bmIndexByte(b *testing.B, index func([]byte, byte) int, n int) {
+ if len(bmbuf) < n {
+ bmbuf = make([]byte, n)
+ }
+ b.SetBytes(int64(n))
+ buf := bmbuf[0:n]
+ buf[n-1] = 'x'
+ for i := 0; i < b.N; i++ {
+ j := index(buf, 'x')
+ if j != n-1 {
+ println("bad index", j)
+ panic("bad index")
+ }
+ }
+ buf[n-1] = '\x00'
}
-func BenchmarkIndexBytePortable4M(b *testing.B) {
- bmIndex(b, IndexBytePortable, 4<<20)
+func BenchmarkEqual32(b *testing.B) { bmEqual(b, Equal, 32) }
+func BenchmarkEqual4K(b *testing.B) { bmEqual(b, Equal, 4<<10) }
+func BenchmarkEqual4M(b *testing.B) { bmEqual(b, Equal, 4<<20) }
+func BenchmarkEqual64M(b *testing.B) { bmEqual(b, Equal, 64<<20) }
+func BenchmarkEqualPort32(b *testing.B) { bmEqual(b, EqualPortable, 32) }
+func BenchmarkEqualPort4K(b *testing.B) { bmEqual(b, EqualPortable, 4<<10) }
+func BenchmarkEqualPortable4M(b *testing.B) { bmEqual(b, EqualPortable, 4<<20) }
+func BenchmarkEqualPortable64M(b *testing.B) { bmEqual(b, EqualPortable, 64<<20) }
+
+func bmEqual(b *testing.B, equal func([]byte, []byte) bool, n int) {
+ if len(bmbuf) < 2*n {
+ bmbuf = make([]byte, 2*n)
+ }
+ b.SetBytes(int64(n))
+ buf1 := bmbuf[0:n]
+ buf2 := bmbuf[n : 2*n]
+ buf1[n-1] = 'x'
+ buf2[n-1] = 'x'
+ for i := 0; i < b.N; i++ {
+ eq := equal(buf1, buf2)
+ if !eq {
+ panic("bad equal")
+ }
+ }
+ buf1[n-1] = '\x00'
+ buf2[n-1] = '\x00'
}
-func BenchmarkIndexBytePortable64M(b *testing.B) {
- bmIndex(b, IndexBytePortable, 64<<20)
+func BenchmarkIndex32(b *testing.B) { bmIndex(b, Index, 32) }
+func BenchmarkIndex4K(b *testing.B) { bmIndex(b, Index, 4<<10) }
+func BenchmarkIndex4M(b *testing.B) { bmIndex(b, Index, 4<<20) }
+func BenchmarkIndex64M(b *testing.B) { bmIndex(b, Index, 64<<20) }
+
+func bmIndex(b *testing.B, index func([]byte, []byte) int, n int) {
+ if len(bmbuf) < n {
+ bmbuf = make([]byte, n)
+ }
+ b.SetBytes(int64(n))
+ buf := bmbuf[0:n]
+ buf[n-1] = 'x'
+ for i := 0; i < b.N; i++ {
+ j := index(buf, buf[n-7:])
+ if j != n-7 {
+ println("bad index", j)
+ panic("bad index")
+ }
+ }
+ buf[n-1] = '\x00'
}
-var bmbuf []byte
+func BenchmarkIndexEasy32(b *testing.B) { bmIndexEasy(b, Index, 32) }
+func BenchmarkIndexEasy4K(b *testing.B) { bmIndexEasy(b, Index, 4<<10) }
+func BenchmarkIndexEasy4M(b *testing.B) { bmIndexEasy(b, Index, 4<<20) }
+func BenchmarkIndexEasy64M(b *testing.B) { bmIndexEasy(b, Index, 64<<20) }
-func bmIndex(b *testing.B, index func([]byte, byte) int, n int) {
+func bmIndexEasy(b *testing.B, index func([]byte, []byte) int, n int) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
}
b.SetBytes(int64(n))
buf := bmbuf[0:n]
buf[n-1] = 'x'
+ buf[n-7] = 'x'
for i := 0; i < b.N; i++ {
- j := index(buf, 'x')
- if j != n-1 {
+ j := index(buf, buf[n-7:])
+ if j != n-7 {
println("bad index", j)
panic("bad index")
}
}
- buf[n-1] = '0'
+ buf[n-1] = '\x00'
+ buf[n-7] = '\x00'
+}
+
+func BenchmarkCount32(b *testing.B) { bmCount(b, Count, 32) }
+func BenchmarkCount4K(b *testing.B) { bmCount(b, Count, 4<<10) }
+func BenchmarkCount4M(b *testing.B) { bmCount(b, Count, 4<<20) }
+func BenchmarkCount64M(b *testing.B) { bmCount(b, Count, 64<<20) }
+
+func bmCount(b *testing.B, count func([]byte, []byte) int, n int) {
+ if len(bmbuf) < n {
+ bmbuf = make([]byte, n)
+ }
+ b.SetBytes(int64(n))
+ buf := bmbuf[0:n]
+ buf[n-1] = 'x'
+ for i := 0; i < b.N; i++ {
+ j := count(buf, buf[n-7:])
+ if j != 1 {
+ println("bad count", j)
+ panic("bad count")
+ }
+ }
+ buf[n-1] = '\x00'
+}
+
+func BenchmarkCountEasy32(b *testing.B) { bmCountEasy(b, Count, 32) }
+func BenchmarkCountEasy4K(b *testing.B) { bmCountEasy(b, Count, 4<<10) }
+func BenchmarkCountEasy4M(b *testing.B) { bmCountEasy(b, Count, 4<<20) }
+func BenchmarkCountEasy64M(b *testing.B) { bmCountEasy(b, Count, 64<<20) }
+
+func bmCountEasy(b *testing.B, count func([]byte, []byte) int, n int) {
+ if len(bmbuf) < n {
+ bmbuf = make([]byte, n)
+ }
+ b.SetBytes(int64(n))
+ buf := bmbuf[0:n]
+ buf[n-1] = 'x'
+ buf[n-7] = 'x'
+ for i := 0; i < b.N; i++ {
+ j := count(buf, buf[n-7:])
+ if j != 1 {
+ println("bad count", j)
+ panic("bad count")
+ }
+ }
+ buf[n-1] = '\x00'
+ buf[n-7] = '\x00'
}
type ExplodeTest struct {
diff --git a/libgo/go/bytes/export_test.go b/libgo/go/bytes/export_test.go
index b65428d9ce8..f61523e60bb 100644
--- a/libgo/go/bytes/export_test.go
+++ b/libgo/go/bytes/export_test.go
@@ -6,3 +6,4 @@ package bytes
// Export func for testing
var IndexBytePortable = indexBytePortable
+var EqualPortable = equalPortable
diff --git a/libgo/go/bytes/indexbyte.c b/libgo/go/bytes/indexbyte.c
index a0a963e93f6..8213b3e3442 100644
--- a/libgo/go/bytes/indexbyte.c
+++ b/libgo/go/bytes/indexbyte.c
@@ -26,3 +26,17 @@ IndexByte (struct __go_open_array s, char b)
return -1;
return p - (char *) s.__values;
}
+
+/* Comparison. */
+
+_Bool Equal (struct __go_open_array a, struct __go_open_array b)
+ asm ("libgo_bytes.bytes.Equal")
+ __attribute__ ((no_split_stack));
+
+_Bool
+Equal (struct __go_open_array a, struct __go_open_array b)
+{
+ if (a.__count != b.__count)
+ return 0;
+ return __builtin_memcmp (a.__values, b.__values, a.__count) == 0;
+}