Skip to content

Commit

Permalink
Fix substr tpl func's int type variant issue
Browse files Browse the repository at this point in the history
`substr` template function takes one or two range arguments. Both
arguments must be int type values but if it is used with a calclation
function e.g. `add`, `len` etc, it causes a wrong type error.

This fixes the issue to allow the function to take other integer type
variant like `int64` etc.

This also includes a small fix on no range argument case.

Fix gohugoio#1190
  • Loading branch information
tatsushid committed Jun 6, 2015
1 parent beeae6a commit 0d35525
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 7 deletions.
33 changes: 29 additions & 4 deletions tpl/template_funcs.go
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
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

0 comments on commit 0d35525

Please sign in to comment.