Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix substr tpl func's int type variant issue #1194

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 29 additions & 4 deletions tpl/template_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,45 @@ func Slicestr(a interface{}, startEnd ...int) (string, error) {
// In addition, borrowing from the extended behavior described at http://php.net/substr,
// if length is given and is negative, then that many characters will be omitted from
// the end of string.
func Substr(a interface{}, nums ...int) (string, error) {
func Substr(a interface{}, nums ...interface{}) (string, error) {
aStr, err := cast.ToStringE(a)
if err != nil {
return "", err
}

var start, length int
toInt := func (v interface{}, message string) (int, error) {
switch i := v.(type) {
case int:
return i, nil
case int8:
return int(i), nil
case int16:
return int(i), nil
case int32:
return int(i), nil
case int64:
return int(i), nil
default:
return 0, errors.New(message)
}
}

switch len(nums) {
case 0:
return "", errors.New("too less arguments")
case 1:
start = nums[0]
if start, err = toInt(nums[0], "start argument must be integer"); err != nil {
return "", err
}
length = len(aStr)
case 2:
start = nums[0]
length = nums[1]
if start, err = toInt(nums[0], "start argument must be integer"); err != nil {
return "", err
}
if length, err = toInt(nums[1], "length argument must be integer"); err != nil {
return "", err
}
default:
return "", errors.New("too many arguments")
}
Expand Down
39 changes: 36 additions & 3 deletions tpl/template_funcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,10 +317,12 @@ func TestSlicestr(t *testing.T) {
}

func TestSubstr(t *testing.T) {
var err error
var n int
for i, this := range []struct {
v1 interface{}
v2 int
v3 int
v2 interface{}
v3 interface{}
expect interface{}
}{
{"abc", 1, 2, "bc"},
Expand All @@ -334,11 +336,30 @@ func TestSubstr(t *testing.T) {
{"abcdef", 1, 100, "bcdef"},
{"abcdef", -100, 3, "abc"},
{"abcdef", -3, -1, "de"},
{"abcdef", 2, nil, "cdef"},
{"abcdef", int8(2), nil, "cdef"},
{"abcdef", int16(2), nil, "cdef"},
{"abcdef", int32(2), nil, "cdef"},
{"abcdef", int64(2), nil, "cdef"},
{"abcdef", 2, int8(3), "cde"},
{"abcdef", 2, int16(3), "cde"},
{"abcdef", 2, int32(3), "cde"},
{"abcdef", 2, int64(3), "cde"},
{123, 1, 3, "23"},
{1.2e3, 0, 4, "1200"},
{tstNoStringer{}, 0, 1, false},
{"abcdef", 2.0, nil, false},
{"abcdef", 2.0, 2, false},
{"abcdef", 2, 2.0, false},
} {
result, err := Substr(this.v1, this.v2, this.v3)
var result string
n = i

if this.v3 == nil {
result, err = Substr(this.v1, this.v2)
} else {
result, err = Substr(this.v1, this.v2, this.v3)
}

if b, ok := this.expect.(bool); ok && !b {
if err == nil {
Expand All @@ -354,6 +375,18 @@ func TestSubstr(t *testing.T) {
}
}
}

n++
_, err = Substr("abcdef")
if err == nil {
t.Errorf("[%d] Substr didn't return an expected error", n)
}

n++
_, err = Substr("abcdef", 1, 2, 3)
if err == nil {
t.Errorf("[%d] Substr didn't return an expected error", n)
}
}

func TestSplit(t *testing.T) {
Expand Down