summaryrefslogtreecommitdiff
path: root/src/pkg/strings
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/strings')
-rw-r--r--src/pkg/strings/Makefile12
-rw-r--r--src/pkg/strings/reader.go92
-rw-r--r--src/pkg/strings/strings.go586
-rw-r--r--src/pkg/strings/strings_test.go929
4 files changed, 0 insertions, 1619 deletions
diff --git a/src/pkg/strings/Makefile b/src/pkg/strings/Makefile
deleted file mode 100644
index c1be58243..000000000
--- a/src/pkg/strings/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# 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.
-
-include ../../Make.inc
-
-TARG=strings
-GOFILES=\
- reader.go\
- strings.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/strings/reader.go b/src/pkg/strings/reader.go
deleted file mode 100644
index 8423f7e45..000000000
--- a/src/pkg/strings/reader.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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 (
- "os"
- "utf8"
-)
-
-// 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) {
- if r.i >= len(r.s) {
- return 0, os.EOF
- }
- n = copy(b, r.s[r.i:])
- r.i += n
- r.prevRune = -1
- return
-}
-
-func (r *Reader) ReadByte() (b byte, err os.Error) {
- if r.i >= len(r.s) {
- return 0, os.EOF
- }
- 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) {
- if r.i >= len(r.s) {
- return 0, 0, os.EOF
- }
- r.prevRune = r.i
- if c := r.s[r.i]; c < utf8.RuneSelf {
- r.i++
- return int(c), 1, nil
- }
- 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, 0, -1} }
diff --git a/src/pkg/strings/strings.go b/src/pkg/strings/strings.go
deleted file mode 100644
index 6afbc7dc2..000000000
--- a/src/pkg/strings/strings.go
+++ /dev/null
@@ -1,586 +0,0 @@
-// 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 implements simple functions to manipulate strings.
-package strings
-
-import (
- "unicode"
- "utf8"
-)
-
-// explode splits s into an array of UTF-8 sequences, one per Unicode character (still strings) up to a maximum of n (n < 0 means no limit).
-// Invalid UTF-8 sequences become correct encodings of U+FFF8.
-func explode(s string, n int) []string {
- if n == 0 {
- return nil
- }
- l := utf8.RuneCountInString(s)
- if n <= 0 || n > l {
- n = l
- }
- a := make([]string, n)
- var size, rune int
- i, cur := 0, 0
- for ; i+1 < n; i++ {
- rune, size = utf8.DecodeRuneInString(s[cur:])
- a[i] = string(rune)
- cur += size
- }
- // add the rest, if there is any
- if cur < len(s) {
- a[i] = s[cur:]
- }
- 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]
- l := len(sep)
- n := 0
- if l == 1 {
- // special case worth making fast
- for i := 0; i < len(s); i++ {
- if s[i] == c {
- n++
- }
- }
- return n
- }
- for i := 0; i+l <= len(s); i++ {
- if s[i] == c && s[i:i+l] == sep {
- n++
- i += l - 1
- }
- }
- return n
-}
-
-// Contains returns true if substr is within s.
-func Contains(s, substr string) bool {
- return Index(s, substr) != -1
-}
-
-// 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]
- if n == 1 {
- // special case worth making fast
- for i := 0; i < len(s); i++ {
- if s[i] == c {
- return i
- }
- }
- return -1
- }
- // n > 1
- for i := 0; i+n <= len(s); i++ {
- if s[i] == c && s[i:i+n] == sep {
- return i
- }
- }
- return -1
-}
-
-// LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
-func LastIndex(s, sep string) int {
- n := len(sep)
- if n == 0 {
- return len(s)
- }
- c := sep[0]
- if n == 1 {
- // special case worth making fast
- for i := len(s) - 1; i >= 0; i-- {
- if s[i] == c {
- return i
- }
- }
- return -1
- }
- // n > 1
- for i := len(s) - n; i >= 0; i-- {
- if s[i] == c && s[i:i+n] == sep {
- return i
- }
- }
- return -1
-}
-
-// IndexRune returns the index of the first instance of the Unicode code point
-// rune, or -1 if rune is not present in s.
-func IndexRune(s string, rune int) int {
- switch {
- case rune < 0x80:
- b := byte(rune)
- for i := 0; i < len(s); i++ {
- if s[i] == b {
- return i
- }
- }
- default:
- for i, c := range s {
- if c == rune {
- return i
- }
- }
- }
- return -1
-}
-
-// IndexAny returns the index of the first instance of any Unicode code point
-// from chars in s, or -1 if no Unicode code point from chars is present in s.
-func IndexAny(s, chars string) int {
- if len(chars) > 0 {
- for i, c := range s {
- for _, m := range chars {
- if c == m {
- return i
- }
- }
- }
- }
- return -1
-}
-
-// LastIndexAny returns the index of the last instance of any Unicode code
-// point from chars in s, or -1 if no Unicode code point from chars is
-// present in s.
-func LastIndexAny(s, chars string) int {
- if len(chars) > 0 {
- for i := len(s); i > 0; {
- rune, size := utf8.DecodeLastRuneInString(s[0:i])
- i -= size
- for _, m := range chars {
- if rune == m {
- return i
- }
- }
- }
- }
- return -1
-}
-
-// Generic split: splits after each instance of sep,
-// including sepSave bytes of sep in the subarrays.
-func genSplit(s, sep string, sepSave, n int) []string {
- if n == 0 {
- return nil
- }
- if sep == "" {
- return explode(s, n)
- }
- if n < 0 {
- n = Count(s, sep) + 1
- }
- c := sep[0]
- start := 0
- a := make([]string, n)
- na := 0
- for i := 0; i+len(sep) <= len(s) && na+1 < n; i++ {
- if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) {
- a[na] = s[start : i+sepSave]
- na++
- start = i + len(sep)
- i += len(sep) - 1
- }
- }
- a[na] = s[start:]
- return a[0 : na+1]
-}
-
-// SplitN slices s into substrings separated by sep and returns a slice of
-// the substrings between those separators.
-// 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 SplitN(s, sep string, n int) []string { return genSplit(s, sep, 0, n) }
-
-// SplitAfterN slices s into substrings after each instance of sep and
-// returns a slice of those substrings.
-// 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 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 {
- return FieldsFunc(s, unicode.IsSpace)
-}
-
-// FieldsFunc splits the string s at each run of Unicode code points c satisfying f(c)
-// and returns an array of slices of s. If all code points in s satisfy f(c) or the
-// string is empty, an empty slice is returned.
-func FieldsFunc(s string, f func(int) bool) []string {
- // First count the fields.
- n := 0
- inField := false
- for _, rune := range s {
- wasInField := inField
- inField = !f(rune)
- if inField && !wasInField {
- n++
- }
- }
-
- // Now create them.
- a := make([]string, n)
- na := 0
- fieldStart := -1 // Set to -1 when looking for start of field.
- for i, rune := range s {
- if f(rune) {
- if fieldStart >= 0 {
- a[na] = s[fieldStart:i]
- na++
- fieldStart = -1
- }
- } else if fieldStart == -1 {
- fieldStart = i
- }
- }
- if fieldStart != -1 { // Last field might end at EOF.
- a[na] = s[fieldStart:]
- }
- 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 := copy(b, a[0])
- for _, s := range a[1:] {
- bp += copy(b[bp:], sep)
- bp += copy(b[bp:], s)
- }
- 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):] == suffix
-}
-
-// Map returns a copy of the string s with all its characters modified
-// according to the mapping function. If mapping returns a negative value, the character is
-// dropped from the string with no replacement.
-func Map(mapping func(rune int) int, s string) string {
- // In the worst case, the string can grow when mapped, making
- // things unpleasant. But it's so rare we barge in assuming it's
- // fine. It could also shrink but that falls out naturally.
- maxbytes := len(s) // length of b
- nbytes := 0 // number of bytes encoded in b
- // The output buffer b is initialized on demand, the first
- // time a character differs.
- var b []byte
-
- for i, c := range s {
- rune := mapping(c)
- if b == nil {
- if rune == c {
- continue
- }
- b = make([]byte, maxbytes)
- nbytes = copy(b, s[:i])
- }
- if rune >= 0 {
- wid := 1
- if rune >= utf8.RuneSelf {
- wid = utf8.RuneLen(rune)
- }
- if nbytes+wid > maxbytes {
- // Grow the buffer.
- maxbytes = maxbytes*2 + utf8.UTFMax
- nb := make([]byte, maxbytes)
- copy(nb, b[0:nbytes])
- b = nb
- }
- nbytes += utf8.EncodeRune(b[nbytes:maxbytes], rune)
- }
- }
- if b == nil {
- return s
- }
- return string(b[0:nbytes])
-}
-
-// Repeat returns a new string consisting of count copies of the string s.
-func Repeat(s string, count int) string {
- b := make([]byte, len(s)*count)
- bp := 0
- for i := 0; i < count; i++ {
- for j := 0; j < len(s); j++ {
- b[bp] = s[j]
- bp++
- }
- }
- 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) }
-
-// ToLower returns a copy of the string s with all Unicode letters mapped to their lower case.
-func ToLower(s string) string { return Map(unicode.ToLower, s) }
-
-// ToTitle returns a copy of the string s with all Unicode letters mapped to their title case.
-func ToTitle(s string) string { return Map(unicode.ToTitle, s) }
-
-// ToUpperSpecial returns a copy of the string s with all Unicode letters mapped to their
-// upper case, giving priority to the special casing rules.
-func ToUpperSpecial(_case unicode.SpecialCase, s string) string {
- return Map(func(r int) int { return _case.ToUpper(r) }, s)
-}
-
-// ToLowerSpecial returns a copy of the string s with all Unicode letters mapped to their
-// lower case, giving priority to the special casing rules.
-func ToLowerSpecial(_case unicode.SpecialCase, s string) string {
- return Map(func(r int) int { return _case.ToLower(r) }, s)
-}
-
-// ToTitleSpecial returns a copy of the string s with all Unicode letters mapped to their
-// title case, giving priority to the special casing rules.
-func ToTitleSpecial(_case unicode.SpecialCase, s string) string {
- return Map(func(r int) int { return _case.ToTitle(r) }, s)
-}
-
-// isSeparator reports whether the rune could mark a word boundary.
-// TODO: update when package unicode captures more of the properties.
-func isSeparator(rune int) bool {
- // ASCII alphanumerics and underscore are not separators
- if rune <= 0x7F {
- switch {
- case '0' <= rune && rune <= '9':
- return false
- case 'a' <= rune && rune <= 'z':
- return false
- case 'A' <= rune && rune <= 'Z':
- return false
- case rune == '_':
- return false
- }
- return true
- }
- // Letters and digits are not separators
- if unicode.IsLetter(rune) || unicode.IsDigit(rune) {
- return false
- }
- // Otherwise, all we can do for now is treat spaces as separators.
- return unicode.IsSpace(rune)
-}
-
-// BUG(r): The rule Title uses for word boundaries does not handle Unicode punctuation properly.
-
-// Title returns a copy of the string s with all Unicode letters that begin words
-// mapped to their title case.
-func Title(s string) string {
- // Use a closure here to remember state.
- // Hackish but effective. Depends on Map scanning in order and calling
- // the closure once per rune.
- prev := ' '
- return Map(
- func(r int) int {
- if isSeparator(prev) {
- prev = r
- return unicode.ToTitle(r)
- }
- prev = r
- return r
- },
- s)
-}
-
-// TrimLeftFunc returns a slice of the string s with all leading
-// Unicode code points c satisfying f(c) removed.
-func TrimLeftFunc(s string, f func(r int) bool) string {
- i := indexFunc(s, f, false)
- if i == -1 {
- return ""
- }
- return s[i:]
-}
-
-// TrimRightFunc returns a slice of the string s with all trailing
-// Unicode code points c satisfying f(c) removed.
-func TrimRightFunc(s string, f func(r int) bool) string {
- i := lastIndexFunc(s, f, false)
- if i >= 0 && s[i] >= utf8.RuneSelf {
- _, wid := utf8.DecodeRuneInString(s[i:])
- i += wid
- } else {
- i++
- }
- return s[0:i]
-}
-
-// TrimFunc returns a slice of the string s with all leading
-// and trailing Unicode code points c satisfying f(c) removed.
-func TrimFunc(s string, f func(r int) bool) string {
- return TrimRightFunc(TrimLeftFunc(s, f), f)
-}
-
-// IndexFunc returns the index into s of the first Unicode
-// code point satisfying f(c), or -1 if none do.
-func IndexFunc(s string, f func(r int) bool) int {
- return indexFunc(s, f, true)
-}
-
-// LastIndexFunc returns the index into s of the last
-// Unicode code point satisfying f(c), or -1 if none do.
-func LastIndexFunc(s string, f func(r int) bool) int {
- return lastIndexFunc(s, f, true)
-}
-
-// indexFunc is the same as IndexFunc except that if
-// truth==false, the sense of the predicate function is
-// inverted.
-func indexFunc(s string, f func(r int) bool, truth bool) int {
- start := 0
- for start < len(s) {
- wid := 1
- rune := int(s[start])
- if rune >= utf8.RuneSelf {
- rune, wid = utf8.DecodeRuneInString(s[start:])
- }
- if f(rune) == truth {
- return start
- }
- start += wid
- }
- return -1
-}
-
-// lastIndexFunc is the same as LastIndexFunc except that if
-// truth==false, the sense of the predicate function is
-// inverted.
-func lastIndexFunc(s string, f func(r int) bool, truth bool) int {
- for i := len(s); i > 0; {
- rune, size := utf8.DecodeLastRuneInString(s[0:i])
- i -= size
- if f(rune) == truth {
- return i
- }
- }
- return -1
-}
-
-func makeCutsetFunc(cutset string) func(rune int) bool {
- return func(rune int) bool { return IndexRune(cutset, rune) != -1 }
-}
-
-// Trim returns a slice of the string s with all leading and
-// trailing Unicode code points contained in cutset removed.
-func Trim(s string, cutset string) string {
- if s == "" || cutset == "" {
- return s
- }
- return TrimFunc(s, makeCutsetFunc(cutset))
-}
-
-// TrimLeft returns a slice of the string s with all leading
-// Unicode code points contained in cutset removed.
-func TrimLeft(s string, cutset string) string {
- if s == "" || cutset == "" {
- return s
- }
- return TrimLeftFunc(s, makeCutsetFunc(cutset))
-}
-
-// TrimRight returns a slice of the string s, with all trailing
-// Unicode code points contained in cutset removed.
-func TrimRight(s string, cutset string) string {
- if s == "" || cutset == "" {
- return s
- }
- return TrimRightFunc(s, makeCutsetFunc(cutset))
-}
-
-// TrimSpace returns a slice of the string s, with all leading
-// and trailing white space removed, as defined by Unicode.
-func TrimSpace(s string) string {
- return TrimFunc(s, unicode.IsSpace)
-}
-
-// Replace returns a copy of the string s with the first n
-// non-overlapping instances of old replaced by new.
-// If n < 0, there is no limit on the number of replacements.
-func Replace(s, old, new string, n int) string {
- if old == new || n == 0 {
- return s // avoid allocation
- }
-
- // Compute number of replacements.
- if m := Count(s, old); m == 0 {
- return s // avoid allocation
- } else if n < 0 || m < n {
- n = m
- }
-
- // Apply replacements to buffer.
- t := make([]byte, len(s)+n*(len(new)-len(old)))
- w := 0
- start := 0
- for i := 0; i < n; i++ {
- j := start
- if len(old) == 0 {
- if i > 0 {
- _, wid := utf8.DecodeRuneInString(s[start:])
- j += wid
- }
- } else {
- j += Index(s[start:], old)
- }
- w += copy(t[w:], s[start:j])
- w += copy(t[w:], new)
- start = j + len(old)
- }
- w += copy(t[w:], s[start:])
- return string(t[0:w])
-}
diff --git a/src/pkg/strings/strings_test.go b/src/pkg/strings/strings_test.go
deleted file mode 100644
index c54617339..000000000
--- a/src/pkg/strings/strings_test.go
+++ /dev/null
@@ -1,929 +0,0 @@
-// 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_test
-
-import (
- "bytes"
- "os"
- "reflect"
- "strconv"
- . "strings"
- "testing"
- "unicode"
- "unsafe"
- "utf8"
-)
-
-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 IndexTest struct {
- s string
- sep string
- out int
-}
-
-var indexTests = []IndexTest{
- {"", "", 0},
- {"", "a", -1},
- {"", "foo", -1},
- {"fo", "foo", -1},
- {"foo", "foo", 0},
- {"oofofoofooo", "f", 2},
- {"oofofoofooo", "foo", 4},
- {"barfoobarfoo", "foo", 3},
- {"foo", "", 0},
- {"foo", "o", 1},
- {"abcABCabc", "A", 3},
- // cases with one byte strings - test special case in Index()
- {"", "a", -1},
- {"x", "a", -1},
- {"x", "x", 0},
- {"abc", "a", 0},
- {"abc", "b", 1},
- {"abc", "c", 2},
- {"abc", "x", -1},
-}
-
-var lastIndexTests = []IndexTest{
- {"", "", 0},
- {"", "a", -1},
- {"", "foo", -1},
- {"fo", "foo", -1},
- {"foo", "foo", 0},
- {"foo", "f", 0},
- {"oofofoofooo", "f", 7},
- {"oofofoofooo", "foo", 7},
- {"barfoobarfoo", "foo", 9},
- {"foo", "", 3},
- {"foo", "o", 2},
- {"abcABCabc", "A", 3},
- {"abcABCabc", "a", 6},
-}
-
-var indexAnyTests = []IndexTest{
- {"", "", -1},
- {"", "a", -1},
- {"", "abc", -1},
- {"a", "", -1},
- {"a", "a", 0},
- {"aaa", "a", 0},
- {"abc", "xyz", -1},
- {"abc", "xcz", 2},
- {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
- {"aRegExp*", ".(|)*+?^$[]", 7},
- {dots + dots + dots, " ", -1},
-}
-var lastIndexAnyTests = []IndexTest{
- {"", "", -1},
- {"", "a", -1},
- {"", "abc", -1},
- {"a", "", -1},
- {"a", "a", 0},
- {"aaa", "a", 2},
- {"abc", "xyz", -1},
- {"abc", "ab", 1},
- {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
- {"a.RegExp*", ".(|)*+?^$[]", 8},
- {dots + dots + dots, " ", -1},
-}
-
-// Execute f on each test case. funcName should be the name of f; it's used
-// in failure reports.
-func runIndexTests(t *testing.T, f func(s, sep string) int, funcName string, testCases []IndexTest) {
- for _, test := range testCases {
- actual := f(test.s, test.sep)
- if actual != test.out {
- t.Errorf("%s(%q,%q) = %v; want %v", funcName, test.s, test.sep, actual, test.out)
- }
- }
-}
-
-func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) }
-func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) }
-func TestIndexAny(t *testing.T) { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) }
-func TestLastIndexAny(t *testing.T) { runIndexTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) }
-
-type IndexRuneTest struct {
- s string
- rune int
- out int
-}
-
-var indexRuneTests = []IndexRuneTest{
- {"a A x", 'A', 2},
- {"some_text=some_value", '=', 9},
- {"☺a", 'a', 3},
- {"a☻☺b", '☺', 4},
-}
-
-func TestIndexRune(t *testing.T) {
- for _, test := range indexRuneTests {
- if actual := IndexRune(test.s, test.rune); actual != test.out {
- t.Errorf("IndexRune(%q,%d)= %v; want %v", test.s, test.rune, actual, test.out)
- }
- }
-}
-
-const benchmarkString = "some_text=some☺value"
-
-func BenchmarkIndexRune(b *testing.B) {
- if got := IndexRune(benchmarkString, '☺'); got != 14 {
- panic("wrong index: got=" + strconv.Itoa(got))
- }
- for i := 0; i < b.N; i++ {
- IndexRune(benchmarkString, '☺')
- }
-}
-
-func BenchmarkIndexRuneFastPath(b *testing.B) {
- if got := IndexRune(benchmarkString, 'v'); got != 17 {
- panic("wrong index: got=" + strconv.Itoa(got))
- }
- for i := 0; i < b.N; i++ {
- IndexRune(benchmarkString, 'v')
- }
-}
-
-func BenchmarkIndex(b *testing.B) {
- if got := Index(benchmarkString, "v"); got != 17 {
- panic("wrong index: got=" + strconv.Itoa(got))
- }
- for i := 0; i < b.N; i++ {
- Index(benchmarkString, "v")
- }
-}
-
-
-type ExplodeTest struct {
- s string
- n int
- a []string
-}
-
-var explodetests = []ExplodeTest{
- {"", -1, []string{}},
- {abcd, 4, []string{"a", "b", "c", "d"}},
- {faces, 3, []string{"☺", "☻", "☹"}},
- {abcd, 2, []string{"a", "bcd"}},
-}
-
-func TestExplode(t *testing.T) {
- for _, tt := range explodetests {
- 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
- }
- s := Join(a, "")
- if s != tt.s {
- t.Errorf(`Join(explode(%q, %d), "") = %q`, tt.s, tt.n, s)
- }
- }
-}
-
-type SplitTest struct {
- s string
- sep string
- n int
- a []string
-}
-
-var splittests = []SplitTest{
- {abcd, "a", 0, nil},
- {abcd, "a", -1, []string{"", "bcd"}},
- {abcd, "z", -1, []string{"abcd"}},
- {abcd, "", -1, []string{"a", "b", "c", "d"}},
- {commas, ",", -1, []string{"1", "2", "3", "4"}},
- {dots, "...", -1, []string{"1", ".2", ".3", ".4"}},
- {faces, "☹", -1, []string{"☺☻", ""}},
- {faces, "~", -1, []string{faces}},
- {faces, "", -1, []string{"☺", "☻", "☹"}},
- {"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}},
- {"1 2", " ", 3, []string{"1", "2"}},
- {"123", "", 2, []string{"1", "23"}},
- {"123", "", 17, []string{"1", "2", "3"}},
-}
-
-func TestSplit(t *testing.T) {
- for _, tt := range splittests {
- 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
- }
- if tt.n == 0 {
- continue
- }
- s := Join(a, tt.sep)
- 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)
- }
- }
- }
-}
-
-var splitaftertests = []SplitTest{
- {abcd, "a", -1, []string{"a", "bcd"}},
- {abcd, "z", -1, []string{"abcd"}},
- {abcd, "", -1, []string{"a", "b", "c", "d"}},
- {commas, ",", -1, []string{"1,", "2,", "3,", "4"}},
- {dots, "...", -1, []string{"1...", ".2...", ".3...", ".4"}},
- {faces, "☹", -1, []string{"☺☻☹", ""}},
- {faces, "~", -1, []string{faces}},
- {faces, "", -1, []string{"☺", "☻", "☹"}},
- {"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}},
- {"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}},
- {"1 2", " ", 3, []string{"1 ", "2"}},
- {"123", "", 2, []string{"1", "23"}},
- {"123", "", 17, []string{"1", "2", "3"}},
-}
-
-func TestSplitAfter(t *testing.T) {
- for _, tt := range splitaftertests {
- 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
- }
- s := Join(a, "")
- 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)
- }
- }
- }
-}
-
-type FieldsTest struct {
- s string
- a []string
-}
-
-var fieldstests = []FieldsTest{
- {"", []string{}},
- {" ", []string{}},
- {" \t ", []string{}},
- {" abc ", []string{"abc"}},
- {"1 2 3 4", []string{"1", "2", "3", "4"}},
- {"1 2 3 4", []string{"1", "2", "3", "4"}},
- {"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}},
- {"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}},
- {"\u2000\u2001\u2002", []string{}},
- {"\n™\t™\n", []string{"™", "™"}},
- {faces, []string{faces}},
-}
-
-func TestFields(t *testing.T) {
- for _, tt := range fieldstests {
- a := Fields(tt.s)
- if !eq(a, tt.a) {
- t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a)
- continue
- }
- }
-}
-
-func TestFieldsFunc(t *testing.T) {
- pred := func(c int) bool { return c == 'X' }
- var fieldsFuncTests = []FieldsTest{
- {"", []string{}},
- {"XX", []string{}},
- {"XXhiXXX", []string{"hi"}},
- {"aXXbXXXcX", []string{"a", "b", "c"}},
- }
- for _, tt := range fieldsFuncTests {
- a := FieldsFunc(tt.s, pred)
- if !eq(a, tt.a) {
- t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a)
- }
- }
-}
-
-
-// Test case for any function which accepts and returns a single string.
-type StringTest struct {
- in, out string
-}
-
-// Execute f on each test case. funcName should be the name of f; it's used
-// in failure reports.
-func runStringTests(t *testing.T, f func(string) string, funcName string, testCases []StringTest) {
- for _, tc := range testCases {
- actual := f(tc.in)
- if actual != tc.out {
- t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out)
- }
- }
-}
-
-var upperTests = []StringTest{
- {"", ""},
- {"abc", "ABC"},
- {"AbC123", "ABC123"},
- {"azAZ09_", "AZAZ09_"},
- {"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char
-}
-
-var lowerTests = []StringTest{
- {"", ""},
- {"abc", "abc"},
- {"AbC123", "abc123"},
- {"azAZ09_", "azaz09_"},
- {"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char
-}
-
-const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000"
-
-var trimSpaceTests = []StringTest{
- {"", ""},
- {"abc", "abc"},
- {space + "abc" + space, "abc"},
- {" ", ""},
- {" \t\r\n \t\t\r\r\n\n ", ""},
- {" \t\r\n x\t\t\r\r\n\n ", "x"},
- {" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"},
- {"1 \t\r\n2", "1 \t\r\n2"},
- {" x\x80", "x\x80"},
- {" x\xc0", "x\xc0"},
- {"x \xc0\xc0 ", "x \xc0\xc0"},
- {"x \xc0", "x \xc0"},
- {"x \xc0 ", "x \xc0"},
- {"x \xc0\xc0 ", "x \xc0\xc0"},
- {"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"},
- {"x ☺ ", "x ☺"},
-}
-
-func tenRunes(rune int) string {
- r := make([]int, 10)
- for i := range r {
- r[i] = rune
- }
- return string(r)
-}
-
-// User-defined self-inverse mapping function
-func rot13(rune int) int {
- step := 13
- if rune >= 'a' && rune <= 'z' {
- return ((rune - 'a' + step) % 26) + 'a'
- }
- if rune >= 'A' && rune <= 'Z' {
- return ((rune - 'A' + step) % 26) + 'A'
- }
- return rune
-}
-
-func TestMap(t *testing.T) {
- // Run a couple of awful growth/shrinkage tests
- a := tenRunes('a')
- // 1. Grow. This triggers two reallocations in Map.
- maxRune := func(rune int) int { return unicode.MaxRune }
- m := Map(maxRune, a)
- expect := tenRunes(unicode.MaxRune)
- if m != expect {
- t.Errorf("growing: expected %q got %q", expect, m)
- }
-
- // 2. Shrink
- minRune := func(rune int) int { return 'a' }
- m = Map(minRune, tenRunes(unicode.MaxRune))
- expect = a
- if m != expect {
- t.Errorf("shrinking: expected %q got %q", expect, m)
- }
-
- // 3. Rot13
- m = Map(rot13, "a to zed")
- expect = "n gb mrq"
- if m != expect {
- t.Errorf("rot13: expected %q got %q", expect, m)
- }
-
- // 4. Rot13^2
- m = Map(rot13, Map(rot13, "a to zed"))
- expect = "a to zed"
- if m != expect {
- t.Errorf("rot13: expected %q got %q", expect, m)
- }
-
- // 5. Drop
- dropNotLatin := func(rune int) int {
- if unicode.Is(unicode.Latin, rune) {
- return rune
- }
- return -1
- }
- m = Map(dropNotLatin, "Hello, 세계")
- expect = "Hello"
- if m != expect {
- t.Errorf("drop: expected %q got %q", expect, m)
- }
-
- // 6. Identity
- identity := func(rune int) int {
- return rune
- }
- orig := "Input string that we expect not to be copied."
- m = Map(identity, orig)
- if (*reflect.StringHeader)(unsafe.Pointer(&orig)).Data !=
- (*reflect.StringHeader)(unsafe.Pointer(&m)).Data {
- t.Error("unexpected copy during identity map")
- }
-}
-
-func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) }
-
-func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) }
-
-func BenchmarkMapNoChanges(b *testing.B) {
- identity := func(rune int) int {
- return rune
- }
- for i := 0; i < b.N; i++ {
- Map(identity, "Some string that won't be modified.")
- }
-}
-
-func TestSpecialCase(t *testing.T) {
- lower := "abcçdefgğhıijklmnoöprsştuüvyz"
- upper := "ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ"
- u := ToUpperSpecial(unicode.TurkishCase, upper)
- if u != upper {
- t.Errorf("Upper(upper) is %s not %s", u, upper)
- }
- u = ToUpperSpecial(unicode.TurkishCase, lower)
- if u != upper {
- t.Errorf("Upper(lower) is %s not %s", u, upper)
- }
- l := ToLowerSpecial(unicode.TurkishCase, lower)
- if l != lower {
- t.Errorf("Lower(lower) is %s not %s", l, lower)
- }
- l = ToLowerSpecial(unicode.TurkishCase, upper)
- if l != lower {
- t.Errorf("Lower(upper) is %s not %s", l, lower)
- }
-}
-
-func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
-
-type TrimTest struct {
- f func(string, string) string
- in, cutset, out string
-}
-
-var trimTests = []TrimTest{
- {Trim, "abba", "a", "bb"},
- {Trim, "abba", "ab", ""},
- {TrimLeft, "abba", "ab", ""},
- {TrimRight, "abba", "ab", ""},
- {TrimLeft, "abba", "a", "bba"},
- {TrimRight, "abba", "a", "abb"},
- {Trim, "<tag>", "<>", "tag"},
- {Trim, "* listitem", " *", "listitem"},
- {Trim, `"quote"`, `"`, "quote"},
- {Trim, "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
- //empty string tests
- {Trim, "abba", "", "abba"},
- {Trim, "", "123", ""},
- {Trim, "", "", ""},
- {TrimLeft, "abba", "", "abba"},
- {TrimLeft, "", "123", ""},
- {TrimLeft, "", "", ""},
- {TrimRight, "abba", "", "abba"},
- {TrimRight, "", "123", ""},
- {TrimRight, "", "", ""},
- {TrimRight, "☺\xc0", "☺", "☺\xc0"},
-}
-
-func TestTrim(t *testing.T) {
- for _, tc := range trimTests {
- actual := tc.f(tc.in, tc.cutset)
- var name string
- switch tc.f {
- case Trim:
- name = "Trim"
- case TrimLeft:
- name = "TrimLeft"
- case TrimRight:
- name = "TrimRight"
- default:
- t.Error("Undefined trim function")
- }
- if actual != tc.out {
- t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
- }
- }
-}
-
-type predicate struct {
- f func(r int) bool
- name string
-}
-
-var isSpace = predicate{unicode.IsSpace, "IsSpace"}
-var isDigit = predicate{unicode.IsDigit, "IsDigit"}
-var isUpper = predicate{unicode.IsUpper, "IsUpper"}
-var isValidRune = predicate{
- func(r int) bool {
- return r != utf8.RuneError
- },
- "IsValidRune",
-}
-
-type TrimFuncTest struct {
- f predicate
- in, out string
-}
-
-func not(p predicate) predicate {
- return predicate{
- func(r int) bool {
- return !p.f(r)
- },
- "not " + p.name,
- }
-}
-
-var trimFuncTests = []TrimFuncTest{
- {isSpace, space + " hello " + space, "hello"},
- {isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"},
- {isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"},
- {not(isSpace), "hello" + space + "hello", space},
- {not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo", "\u0e50\u0e521234\u0e50\u0e51"},
- {isValidRune, "ab\xc0a\xc0cd", "\xc0a\xc0"},
- {not(isValidRune), "\xc0a\xc0", "a"},
-}
-
-func TestTrimFunc(t *testing.T) {
- for _, tc := range trimFuncTests {
- actual := TrimFunc(tc.in, tc.f.f)
- if actual != tc.out {
- t.Errorf("TrimFunc(%q, %q) = %q; want %q", tc.in, tc.f.name, actual, tc.out)
- }
- }
-}
-
-type IndexFuncTest struct {
- in string
- f predicate
- first, last int
-}
-
-var indexFuncTests = []IndexFuncTest{
- {"", isValidRune, -1, -1},
- {"abc", isDigit, -1, -1},
- {"0123", isDigit, 0, 3},
- {"a1b", isDigit, 1, 1},
- {space, isSpace, 0, len(space) - 3}, // last rune in space is 3 bytes
- {"\u0e50\u0e5212hello34\u0e50\u0e51", isDigit, 0, 18},
- {"\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", isUpper, 0, 34},
- {"12\u0e50\u0e52hello34\u0e50\u0e51", not(isDigit), 8, 12},
-
- // tests of invalid UTF-8
- {"\x801", isDigit, 1, 1},
- {"\x80abc", isDigit, -1, -1},
- {"\xc0a\xc0", isValidRune, 1, 1},
- {"\xc0a\xc0", not(isValidRune), 0, 2},
- {"\xc0☺\xc0", not(isValidRune), 0, 4},
- {"\xc0☺\xc0\xc0", not(isValidRune), 0, 5},
- {"ab\xc0a\xc0cd", not(isValidRune), 2, 4},
- {"a\xe0\x80cd", not(isValidRune), 1, 2},
- {"\x80\x80\x80\x80", not(isValidRune), 0, 3},
-}
-
-func TestIndexFunc(t *testing.T) {
- for _, tc := range indexFuncTests {
- first := IndexFunc(tc.in, tc.f.f)
- if first != tc.first {
- t.Errorf("IndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, first, tc.first)
- }
- last := LastIndexFunc(tc.in, tc.f.f)
- if last != tc.last {
- t.Errorf("LastIndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, last, tc.last)
- }
- }
-}
-
-func equal(m string, s1, s2 string, t *testing.T) bool {
- if s1 == s2 {
- return true
- }
- e1 := Split(s1, "")
- e2 := Split(s2, "")
- for i, c1 := range e1 {
- if i > len(e2) {
- break
- }
- r1, _ := utf8.DecodeRuneInString(c1)
- r2, _ := utf8.DecodeRuneInString(e2[i])
- if r1 != r2 {
- t.Errorf("%s diff at %d: U+%04X U+%04X", m, i, r1, r2)
- }
- }
- return false
-}
-
-func TestCaseConsistency(t *testing.T) {
- // Make a string of all the runes.
- numRunes := unicode.MaxRune + 1
- if testing.Short() {
- numRunes = 1000
- }
- a := make([]int, numRunes)
- for i := range a {
- a[i] = i
- }
- s := string(a)
- // convert the cases.
- upper := ToUpper(s)
- lower := ToLower(s)
-
- // Consistency checks
- if n := utf8.RuneCountInString(upper); n != numRunes {
- t.Error("rune count wrong in upper:", n)
- }
- if n := utf8.RuneCountInString(lower); n != numRunes {
- t.Error("rune count wrong in lower:", n)
- }
- if !equal("ToUpper(upper)", ToUpper(upper), upper, t) {
- t.Error("ToUpper(upper) consistency fail")
- }
- if !equal("ToLower(lower)", ToLower(lower), lower, t) {
- t.Error("ToLower(lower) consistency fail")
- }
- /*
- These fail because of non-one-to-oneness of the data, such as multiple
- upper case 'I' mapping to 'i'. We comment them out but keep them for
- interest.
- For instance: CAPITAL LETTER I WITH DOT ABOVE:
- unicode.ToUpper(unicode.ToLower('\u0130')) != '\u0130'
-
- if !equal("ToUpper(lower)", ToUpper(lower), upper, t) {
- t.Error("ToUpper(lower) consistency fail");
- }
- if !equal("ToLower(upper)", ToLower(upper), lower, t) {
- t.Error("ToLower(upper) consistency fail");
- }
- */
-}
-
-type RepeatTest struct {
- in, out string
- count int
-}
-
-var RepeatTests = []RepeatTest{
- {"", "", 0},
- {"", "", 1},
- {"", "", 2},
- {"-", "", 0},
- {"-", "-", 1},
- {"-", "----------", 10},
- {"abc ", "abc abc abc ", 3},
-}
-
-func TestRepeat(t *testing.T) {
- for _, tt := range RepeatTests {
- a := Repeat(tt.in, tt.count)
- if !equal("Repeat(s)", a, tt.out, t) {
- t.Errorf("Repeat(%v, %d) = %v; want %v", tt.in, tt.count, a, tt.out)
- continue
- }
- }
-}
-
-func runesEqual(a, b []int) bool {
- if len(a) != len(b) {
- return false
- }
- for i, r := range a {
- if r != b[i] {
- return false
- }
- }
- return true
-}
-
-type RunesTest struct {
- in string
- out []int
- lossy bool
-}
-
-var RunesTests = []RunesTest{
- {"", []int{}, false},
- {" ", []int{32}, false},
- {"ABC", []int{65, 66, 67}, false},
- {"abc", []int{97, 98, 99}, false},
- {"\u65e5\u672c\u8a9e", []int{26085, 26412, 35486}, false},
- {"ab\x80c", []int{97, 98, 0xFFFD, 99}, true},
- {"ab\xc0c", []int{97, 98, 0xFFFD, 99}, true},
-}
-
-func TestRunes(t *testing.T) {
- for _, tt := range RunesTests {
- a := []int(tt.in)
- if !runesEqual(a, tt.out) {
- t.Errorf("[]int(%q) = %v; want %v", tt.in, a, tt.out)
- continue
- }
- if !tt.lossy {
- // can only test reassembly if we didn't lose information
- s := string(a)
- if s != tt.in {
- t.Errorf("string([]int(%q)) = %x; want %x", tt.in, s, tt.in)
- }
- }
- }
-}
-
-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, z, e := reader.ReadRune()
- if e == os.EOF {
- break
- }
- if e != nil {
- t.Errorf("Reading %q: %s", s, e)
- 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)
- }
- }
-}
-
-type ReplaceTest struct {
- in string
- old, new string
- n int
- out string
-}
-
-var ReplaceTests = []ReplaceTest{
- {"hello", "l", "L", 0, "hello"},
- {"hello", "l", "L", -1, "heLLo"},
- {"hello", "x", "X", -1, "hello"},
- {"", "x", "X", -1, ""},
- {"radar", "r", "<r>", -1, "<r>ada<r>"},
- {"", "", "<>", -1, "<>"},
- {"banana", "a", "<>", -1, "b<>n<>n<>"},
- {"banana", "a", "<>", 1, "b<>nana"},
- {"banana", "a", "<>", 1000, "b<>n<>n<>"},
- {"banana", "an", "<>", -1, "b<><>a"},
- {"banana", "ana", "<>", -1, "b<>na"},
- {"banana", "", "<>", -1, "<>b<>a<>n<>a<>n<>a<>"},
- {"banana", "", "<>", 10, "<>b<>a<>n<>a<>n<>a<>"},
- {"banana", "", "<>", 6, "<>b<>a<>n<>a<>n<>a"},
- {"banana", "", "<>", 5, "<>b<>a<>n<>a<>na"},
- {"banana", "", "<>", 1, "<>banana"},
- {"banana", "a", "a", -1, "banana"},
- {"banana", "a", "a", 1, "banana"},
- {"☺☻☹", "", "<>", -1, "<>☺<>☻<>☹<>"},
-}
-
-func TestReplace(t *testing.T) {
- for _, tt := range ReplaceTests {
- if s := Replace(tt.in, tt.old, tt.new, tt.n); s != tt.out {
- t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out)
- }
- }
-}
-
-type TitleTest struct {
- in, out string
-}
-
-var TitleTests = []TitleTest{
- {"", ""},
- {"a", "A"},
- {" aaa aaa aaa ", " Aaa Aaa Aaa "},
- {" Aaa Aaa Aaa ", " Aaa Aaa Aaa "},
- {"123a456", "123a456"},
- {"double-blind", "Double-Blind"},
- {"ÿøû", "Ÿøû"},
-}
-
-func TestTitle(t *testing.T) {
- for _, tt := range TitleTests {
- if s := Title(tt.in); s != tt.out {
- t.Errorf("Title(%q) = %q, want %q", tt.in, s, tt.out)
- }
- }
-}
-
-type ContainsTest struct {
- str, substr string
- expected bool
-}
-
-var ContainsTests = []ContainsTest{
- {"abc", "bc", true},
- {"abc", "bcd", false},
- {"abc", "", true},
- {"", "a", false},
-}
-
-func TestContains(t *testing.T) {
- for _, ct := range ContainsTests {
- if Contains(ct.str, ct.substr) != ct.expected {
- t.Errorf("Contains(%s, %s) = %v, want %v",
- ct.str, ct.substr, !ct.expected, ct.expected)
- }
- }
-}