diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-01-12 01:31:45 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-01-12 01:31:45 +0000 |
commit | 26ae0101ebafafea33beadccea3056f4b5e135e8 (patch) | |
tree | 86a3b8019380d5fad53258c4baba3dd9e1e7c736 /libgo/go/bytes | |
parent | c8142b20a95ae9c6bd0bac8c5a545b27402836fe (diff) | |
download | gcc-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.go | 55 | ||||
-rw-r--r-- | libgo/go/bytes/bytes_test.go | 147 | ||||
-rw-r--r-- | libgo/go/bytes/export_test.go | 1 | ||||
-rw-r--r-- | libgo/go/bytes/indexbyte.c | 14 |
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; +} |