aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/strings
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 15:47:21 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 15:47:21 +0000
commitadb0401dac41c81571722312d4586b2693f95aa6 (patch)
treeea2b52e3c258d6b6d9356977c683c7f72a4a5fd5 /libgo/go/strings
parent5548ca3540bccbc908a45942896d635ea5f1c23f (diff)
downloadgcc-adb0401dac41c81571722312d4586b2693f95aa6.zip
gcc-adb0401dac41c81571722312d4586b2693f95aa6.tar.gz
gcc-adb0401dac41c81571722312d4586b2693f95aa6.tar.bz2
Update Go library to r60.
From-SVN: r178910
Diffstat (limited to 'libgo/go/strings')
-rw-r--r--libgo/go/strings/reader.go74
-rw-r--r--libgo/go/strings/strings.go27
-rw-r--r--libgo/go/strings/strings_test.go89
3 files changed, 153 insertions, 37 deletions
diff --git a/libgo/go/strings/reader.go b/libgo/go/strings/reader.go
index 914faa0..eb515de 100644
--- a/libgo/go/strings/reader.go
+++ b/libgo/go/strings/reader.go
@@ -9,53 +9,83 @@ import (
"utf8"
)
-// A Reader satisfies calls to Read, ReadByte, and ReadRune by
-// reading from a string.
-type Reader string
+// A Reader implements the io.Reader, io.ByteScanner, and
+// io.RuneScanner interfaces by reading from a string.
+type Reader struct {
+ s string
+ i int // current reading index
+ prevRune int // index of previous rune; or < 0
+}
+
+// Len returns the number of bytes of the unread portion of the
+// string.
+func (r *Reader) Len() int {
+ return len(r.s) - r.i
+}
func (r *Reader) Read(b []byte) (n int, err os.Error) {
- s := *r
- if len(s) == 0 {
+ if r.i >= len(r.s) {
return 0, os.EOF
}
- for n < len(s) && n < len(b) {
- b[n] = s[n]
- n++
- }
- *r = s[n:]
+ n = copy(b, r.s[r.i:])
+ r.i += n
+ r.prevRune = -1
return
}
func (r *Reader) ReadByte() (b byte, err os.Error) {
- s := *r
- if len(s) == 0 {
+ if r.i >= len(r.s) {
return 0, os.EOF
}
- b = s[0]
- *r = s[1:]
+ b = r.s[r.i]
+ r.i++
+ r.prevRune = -1
return
}
+// UnreadByte moves the reading position back by one byte.
+// It is an error to call UnreadByte if nothing has been
+// read yet.
+func (r *Reader) UnreadByte() os.Error {
+ if r.i <= 0 {
+ return os.NewError("strings.Reader: at beginning of string")
+ }
+ r.i--
+ r.prevRune = -1
+ return nil
+}
+
// ReadRune reads and returns the next UTF-8-encoded
// Unicode code point from the buffer.
// If no bytes are available, the error returned is os.EOF.
// If the bytes are an erroneous UTF-8 encoding, it
// consumes one byte and returns U+FFFD, 1.
func (r *Reader) ReadRune() (rune int, size int, err os.Error) {
- s := *r
- if len(s) == 0 {
+ if r.i >= len(r.s) {
return 0, 0, os.EOF
}
- c := s[0]
- if c < utf8.RuneSelf {
- *r = s[1:]
+ r.prevRune = r.i
+ if c := r.s[r.i]; c < utf8.RuneSelf {
+ r.i++
return int(c), 1, nil
}
- rune, size = utf8.DecodeRuneInString(string(s))
- *r = s[size:]
+ rune, size = utf8.DecodeRuneInString(r.s[r.i:])
+ r.i += size
return
}
+// UnreadRune causes the next call to ReadRune to return the same rune
+// as the previous call to ReadRune.
+// The last method called on r must have been ReadRune.
+func (r *Reader) UnreadRune() os.Error {
+ if r.prevRune < 0 {
+ return os.NewError("strings.Reader: previous operation was not ReadRune")
+ }
+ r.i = r.prevRune
+ r.prevRune = -1
+ return nil
+}
+
// NewReader returns a new Reader reading from s.
// It is similar to bytes.NewBufferString but more efficient and read-only.
-func NewReader(s string) *Reader { return (*Reader)(&s) }
+func NewReader(s string) *Reader { return &Reader{s, 0, -1} }
diff --git a/libgo/go/strings/strings.go b/libgo/go/strings/strings.go
index bfd0571..c547297 100644
--- a/libgo/go/strings/strings.go
+++ b/libgo/go/strings/strings.go
@@ -198,26 +198,40 @@ func genSplit(s, sep string, sepSave, n int) []string {
return a[0 : na+1]
}
-// Split slices s into substrings separated by sep and returns a slice of
+// SplitN slices s into substrings separated by sep and returns a slice of
// the substrings between those separators.
-// If sep is empty, Split splits after each UTF-8 sequence.
+// If sep is empty, SplitN splits after each UTF-8 sequence.
// The count determines the number of substrings to return:
// n > 0: at most n substrings; the last substring will be the unsplit remainder.
// n == 0: the result is nil (zero substrings)
// n < 0: all substrings
-func Split(s, sep string, n int) []string { return genSplit(s, sep, 0, n) }
+func SplitN(s, sep string, n int) []string { return genSplit(s, sep, 0, n) }
-// SplitAfter slices s into substrings after each instance of sep and
+// SplitAfterN slices s into substrings after each instance of sep and
// returns a slice of those substrings.
-// If sep is empty, Split splits after each UTF-8 sequence.
+// If sep is empty, SplitAfterN splits after each UTF-8 sequence.
// The count determines the number of substrings to return:
// n > 0: at most n substrings; the last substring will be the unsplit remainder.
// n == 0: the result is nil (zero substrings)
// n < 0: all substrings
-func SplitAfter(s, sep string, n int) []string {
+func SplitAfterN(s, sep string, n int) []string {
return genSplit(s, sep, len(sep), n)
}
+// Split slices s into all substrings separated by sep and returns a slice of
+// the substrings between those separators.
+// If sep is empty, Split splits after each UTF-8 sequence.
+// It is equivalent to SplitN with a count of -1.
+func Split(s, sep string) []string { return genSplit(s, sep, 0, -1) }
+
+// SplitAfter slices s into all substrings after each instance of sep and
+// returns a slice of those substrings.
+// 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 string) []string {
+ return genSplit(s, sep, len(sep), -1)
+}
+
// Fields splits the string s around each instance of one or more consecutive white space
// characters, returning an array of substrings of s or an empty list if s contains only white space.
func Fields(s string) []string {
@@ -349,7 +363,6 @@ func Repeat(s string, count int) string {
return string(b)
}
-
// ToUpper returns a copy of the string s with all Unicode letters mapped to their upper case.
func ToUpper(s string) string { return Map(unicode.ToUpper, s) }
diff --git a/libgo/go/strings/strings_test.go b/libgo/go/strings/strings_test.go
index c45b148..409d4da 100644
--- a/libgo/go/strings/strings_test.go
+++ b/libgo/go/strings/strings_test.go
@@ -5,6 +5,7 @@
package strings_test
import (
+ "bytes"
"os"
"reflect"
"strconv"
@@ -169,7 +170,6 @@ func BenchmarkIndex(b *testing.B) {
}
}
-
type ExplodeTest struct {
s string
n int
@@ -185,7 +185,7 @@ var explodetests = []ExplodeTest{
func TestExplode(t *testing.T) {
for _, tt := range explodetests {
- a := Split(tt.s, "", tt.n)
+ a := SplitN(tt.s, "", tt.n)
if !eq(a, tt.a) {
t.Errorf("explode(%q, %d) = %v; want %v", tt.s, tt.n, a, tt.a)
continue
@@ -222,7 +222,7 @@ var splittests = []SplitTest{
func TestSplit(t *testing.T) {
for _, tt := range splittests {
- a := Split(tt.s, tt.sep, tt.n)
+ a := SplitN(tt.s, tt.sep, tt.n)
if !eq(a, tt.a) {
t.Errorf("Split(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, a, tt.a)
continue
@@ -234,6 +234,12 @@ func TestSplit(t *testing.T) {
if 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(tt.s, tt.sep)
+ if !reflect.DeepEqual(a, b) {
+ t.Errorf("Split disagrees with SplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
+ }
+ }
}
}
@@ -255,7 +261,7 @@ var splitaftertests = []SplitTest{
func TestSplitAfter(t *testing.T) {
for _, tt := range splitaftertests {
- a := SplitAfter(tt.s, tt.sep, tt.n)
+ a := SplitAfterN(tt.s, tt.sep, tt.n)
if !eq(a, tt.a) {
t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, a, tt.a)
continue
@@ -264,6 +270,12 @@ func TestSplitAfter(t *testing.T) {
if 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(tt.s, tt.sep)
+ if !reflect.DeepEqual(a, b) {
+ t.Errorf("SplitAfter disagrees with SplitAfterN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a)
+ }
+ }
}
}
@@ -312,7 +324,6 @@ func TestFieldsFunc(t *testing.T) {
}
}
-
// Test case for any function which accepts and returns a single string.
type StringTest struct {
in, out string
@@ -622,8 +633,8 @@ func equal(m string, s1, s2 string, t *testing.T) bool {
if s1 == s2 {
return true
}
- e1 := Split(s1, "", -1)
- e2 := Split(s2, "", -1)
+ e1 := Split(s1, "")
+ e2 := Split(s2, "")
for i, c1 := range e1 {
if i > len(e2) {
break
@@ -751,13 +762,56 @@ func TestRunes(t *testing.T) {
}
}
+func TestReadByte(t *testing.T) {
+ testStrings := []string{"", abcd, faces, commas}
+ for _, s := range testStrings {
+ reader := NewReader(s)
+ if e := reader.UnreadByte(); e == nil {
+ t.Errorf("Unreading %q at beginning: expected error", s)
+ }
+ var res bytes.Buffer
+ for {
+ b, e := reader.ReadByte()
+ if e == os.EOF {
+ break
+ }
+ if e != nil {
+ t.Errorf("Reading %q: %s", s, e)
+ break
+ }
+ res.WriteByte(b)
+ // unread and read again
+ e = reader.UnreadByte()
+ if e != nil {
+ t.Errorf("Unreading %q: %s", s, e)
+ break
+ }
+ b1, e := reader.ReadByte()
+ if e != nil {
+ t.Errorf("Reading %q after unreading: %s", s, e)
+ break
+ }
+ if b1 != b {
+ t.Errorf("Reading %q after unreading: want byte %q, got %q", s, b, b1)
+ break
+ }
+ }
+ if res.String() != s {
+ t.Errorf("Reader(%q).ReadByte() produced %q", s, res.String())
+ }
+ }
+}
+
func TestReadRune(t *testing.T) {
testStrings := []string{"", abcd, faces, commas}
for _, s := range testStrings {
reader := NewReader(s)
+ if e := reader.UnreadRune(); e == nil {
+ t.Errorf("Unreading %q at beginning: expected error", s)
+ }
res := ""
for {
- r, _, e := reader.ReadRune()
+ r, z, e := reader.ReadRune()
if e == os.EOF {
break
}
@@ -766,6 +820,25 @@ func TestReadRune(t *testing.T) {
break
}
res += string(r)
+ // unread and read again
+ e = reader.UnreadRune()
+ if e != nil {
+ t.Errorf("Unreading %q: %s", s, e)
+ break
+ }
+ r1, z1, e := reader.ReadRune()
+ if e != nil {
+ t.Errorf("Reading %q after unreading: %s", s, e)
+ break
+ }
+ if r1 != r {
+ t.Errorf("Reading %q after unreading: want rune %q, got %q", s, r, r1)
+ break
+ }
+ if z1 != z {
+ t.Errorf("Reading %q after unreading: want size %d, got %d", s, z, z1)
+ break
+ }
}
if res != s {
t.Errorf("Reader(%q).ReadRune() produced %q", s, res)