ref: 51cabe6fafe5b18ce27962b7ec469f69fd5e2229
parent: be44345272276264719ede32447ce62fa92aa508
author: Tatsushi Demachi <tdemachi@gmail.com>
date: Sat Jun 6 20:21:14 EDT 2015
Fix substr tpl func's int type variant issue `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 #1190
--- a/tpl/template_funcs.go
+++ b/tpl/template_funcs.go
@@ -170,7 +170,7 @@
// 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
@@ -177,13 +177,38 @@
}
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")}
--- a/tpl/template_funcs_test.go
+++ b/tpl/template_funcs_test.go
@@ -317,10 +317,12 @@
}
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"},@@ -334,12 +336,31 @@
{"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 { t.Errorf("[%d] Substr didn't return an expected error", i)@@ -353,6 +374,18 @@
t.Errorf("[%d] got %s but expected %s", i, result, this.expect)}
}
+ }
+
+ 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)}
}
--
⑨