mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
bytes: restore old Trim/TrimLeft behavior for nil
Keep returning nil for the cases where we historically returned nil, even though this is slightly different for TrimLeft and TrimRight. Fixes #51793 Change-Id: Ifbdfc6b09d52b8e063cfe6341019f9b2eb8b70e9 Reviewed-on: https://go-review.googlesource.com/c/go/+/393876 Trust: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
460fd63ccc
commit
32fdad19a2
2 changed files with 106 additions and 11 deletions
|
|
@ -909,7 +909,11 @@ func containsRune(s string, r rune) bool {
|
||||||
// Trim returns a subslice of s by slicing off all leading and
|
// Trim returns a subslice of s by slicing off all leading and
|
||||||
// trailing UTF-8-encoded code points contained in cutset.
|
// trailing UTF-8-encoded code points contained in cutset.
|
||||||
func Trim(s []byte, cutset string) []byte {
|
func Trim(s []byte, cutset string) []byte {
|
||||||
if len(s) == 0 || cutset == "" {
|
if len(s) == 0 {
|
||||||
|
// This is what we've historically done.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if cutset == "" {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
|
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
|
||||||
|
|
@ -924,7 +928,11 @@ func Trim(s []byte, cutset string) []byte {
|
||||||
// TrimLeft returns a subslice of s by slicing off all leading
|
// TrimLeft returns a subslice of s by slicing off all leading
|
||||||
// UTF-8-encoded code points contained in cutset.
|
// UTF-8-encoded code points contained in cutset.
|
||||||
func TrimLeft(s []byte, cutset string) []byte {
|
func TrimLeft(s []byte, cutset string) []byte {
|
||||||
if len(s) == 0 || cutset == "" {
|
if len(s) == 0 {
|
||||||
|
// This is what we've historically done.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if cutset == "" {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
|
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
|
||||||
|
|
@ -940,6 +948,10 @@ func trimLeftByte(s []byte, c byte) []byte {
|
||||||
for len(s) > 0 && s[0] == c {
|
for len(s) > 0 && s[0] == c {
|
||||||
s = s[1:]
|
s = s[1:]
|
||||||
}
|
}
|
||||||
|
if len(s) == 0 {
|
||||||
|
// This is what we've historically done.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -950,6 +962,10 @@ func trimLeftASCII(s []byte, as *asciiSet) []byte {
|
||||||
}
|
}
|
||||||
s = s[1:]
|
s = s[1:]
|
||||||
}
|
}
|
||||||
|
if len(s) == 0 {
|
||||||
|
// This is what we've historically done.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -964,6 +980,10 @@ func trimLeftUnicode(s []byte, cutset string) []byte {
|
||||||
}
|
}
|
||||||
s = s[n:]
|
s = s[n:]
|
||||||
}
|
}
|
||||||
|
if len(s) == 0 {
|
||||||
|
// This is what we've historically done.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1278,24 +1278,69 @@ var trimTests = []TrimTest{
|
||||||
{"TrimSuffix", "aabb", "b", "aab"},
|
{"TrimSuffix", "aabb", "b", "aab"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TrimNilTest struct {
|
||||||
|
f string
|
||||||
|
in []byte
|
||||||
|
arg string
|
||||||
|
out []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
var trimNilTests = []TrimNilTest{
|
||||||
|
{"Trim", nil, "", nil},
|
||||||
|
{"Trim", []byte{}, "", nil},
|
||||||
|
{"Trim", []byte{'a'}, "a", nil},
|
||||||
|
{"Trim", []byte{'a', 'a'}, "a", nil},
|
||||||
|
{"Trim", []byte{'a'}, "ab", nil},
|
||||||
|
{"Trim", []byte{'a', 'b'}, "ab", nil},
|
||||||
|
{"Trim", []byte("☺"), "☺", nil},
|
||||||
|
{"TrimLeft", nil, "", nil},
|
||||||
|
{"TrimLeft", []byte{}, "", nil},
|
||||||
|
{"TrimLeft", []byte{'a'}, "a", nil},
|
||||||
|
{"TrimLeft", []byte{'a', 'a'}, "a", nil},
|
||||||
|
{"TrimLeft", []byte{'a'}, "ab", nil},
|
||||||
|
{"TrimLeft", []byte{'a', 'b'}, "ab", nil},
|
||||||
|
{"TrimLeft", []byte("☺"), "☺", nil},
|
||||||
|
{"TrimRight", nil, "", nil},
|
||||||
|
{"TrimRight", []byte{}, "", []byte{}},
|
||||||
|
{"TrimRight", []byte{'a'}, "a", []byte{}},
|
||||||
|
{"TrimRight", []byte{'a', 'a'}, "a", []byte{}},
|
||||||
|
{"TrimRight", []byte{'a'}, "ab", []byte{}},
|
||||||
|
{"TrimRight", []byte{'a', 'b'}, "ab", []byte{}},
|
||||||
|
{"TrimRight", []byte("☺"), "☺", []byte{}},
|
||||||
|
{"TrimPrefix", nil, "", nil},
|
||||||
|
{"TrimPrefix", []byte{}, "", []byte{}},
|
||||||
|
{"TrimPrefix", []byte{'a'}, "a", []byte{}},
|
||||||
|
{"TrimPrefix", []byte("☺"), "☺", []byte{}},
|
||||||
|
{"TrimSuffix", nil, "", nil},
|
||||||
|
{"TrimSuffix", []byte{}, "", []byte{}},
|
||||||
|
{"TrimSuffix", []byte{'a'}, "a", []byte{}},
|
||||||
|
{"TrimSuffix", []byte("☺"), "☺", []byte{}},
|
||||||
|
}
|
||||||
|
|
||||||
func TestTrim(t *testing.T) {
|
func TestTrim(t *testing.T) {
|
||||||
for _, tc := range trimTests {
|
toFn := func(name string) (func([]byte, string) []byte, func([]byte, []byte) []byte) {
|
||||||
name := tc.f
|
|
||||||
var f func([]byte, string) []byte
|
|
||||||
var fb func([]byte, []byte) []byte
|
|
||||||
switch name {
|
switch name {
|
||||||
case "Trim":
|
case "Trim":
|
||||||
f = Trim
|
return Trim, nil
|
||||||
case "TrimLeft":
|
case "TrimLeft":
|
||||||
f = TrimLeft
|
return TrimLeft, nil
|
||||||
case "TrimRight":
|
case "TrimRight":
|
||||||
f = TrimRight
|
return TrimRight, nil
|
||||||
case "TrimPrefix":
|
case "TrimPrefix":
|
||||||
fb = TrimPrefix
|
return nil, TrimPrefix
|
||||||
case "TrimSuffix":
|
case "TrimSuffix":
|
||||||
fb = TrimSuffix
|
return nil, TrimSuffix
|
||||||
default:
|
default:
|
||||||
t.Errorf("Undefined trim function %s", name)
|
t.Errorf("Undefined trim function %s", name)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range trimTests {
|
||||||
|
name := tc.f
|
||||||
|
f, fb := toFn(name)
|
||||||
|
if f == nil && fb == nil {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
var actual string
|
var actual string
|
||||||
if f != nil {
|
if f != nil {
|
||||||
|
|
@ -1307,6 +1352,36 @@ func TestTrim(t *testing.T) {
|
||||||
t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out)
|
t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, tc := range trimNilTests {
|
||||||
|
name := tc.f
|
||||||
|
f, fb := toFn(name)
|
||||||
|
if f == nil && fb == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var actual []byte
|
||||||
|
if f != nil {
|
||||||
|
actual = f(tc.in, tc.arg)
|
||||||
|
} else {
|
||||||
|
actual = fb(tc.in, []byte(tc.arg))
|
||||||
|
}
|
||||||
|
report := func(s []byte) string {
|
||||||
|
if s == nil {
|
||||||
|
return "nil"
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%q", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(actual) != 0 {
|
||||||
|
t.Errorf("%s(%s, %q) returned non-empty value", name, report(tc.in), tc.arg)
|
||||||
|
} else {
|
||||||
|
actualNil := actual == nil
|
||||||
|
outNil := tc.out == nil
|
||||||
|
if actualNil != outNil {
|
||||||
|
t.Errorf("%s(%s, %q) got nil %t; want nil %t", name, report(tc.in), tc.arg, actualNil, outNil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type predicate struct {
|
type predicate struct {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue