ref: 5b51b3b9fb19d8d20e99d3c249c0052793abe50a
parent: d313bc78a478f9457ce8b496ede0b231e6b4d0f1
author: Benny Wu <benzwu@gmail.com>
date: Fri Aug 14 11:36:56 EDT 2015
Slicestr fix for other int type param Fixes #1347
--- a/tpl/template_funcs.go
+++ b/tpl/template_funcs.go
@@ -128,32 +128,65 @@
return left, right
}
+// Taken out from Substr, to be used by Slicestr too.
+func toInt(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)
+ }
+}
+
// Slicing in Slicestr is done by specifying a half-open range with
// two indices, start and end. 1 and 4 creates a slice including elements 1 through 3.
// The end index can be omitted, it defaults to the string's length.
-func Slicestr(a interface{}, startEnd ...int) (string, error) {+func Slicestr(a interface{}, startEnd ...interface{}) (string, error) {aStr, err := cast.ToStringE(a)
if err != nil {return "", err
}
- if len(startEnd) > 2 {+ var argStart, argEnd int
+
+ argNum := len(startEnd)
+
+ if argNum > 0 {+ if argStart, err = toInt(startEnd[0], "start argument must be integer"); err != nil {+ return "", err
+ }
+ }
+ if argNum > 1 {+ if argEnd, err = toInt(startEnd[1], "end argument must be integer"); err != nil {+ return "", err
+ }
+ }
+
+ if argNum > 2 { return "", errors.New("too many arguments")}
asRunes := []rune(aStr)
- if len(startEnd) > 0 && (startEnd[0] < 0 || startEnd[0] >= len(asRunes)) {+ if argNum > 0 && (argStart < 0 || argStart >= len(asRunes)) { return "", errors.New("slice bounds out of range")}
- if len(startEnd) == 2 {- if startEnd[1] < 0 || startEnd[1] > len(asRunes) {+ if argNum == 2 {+ if argEnd < 0 || argEnd > len(asRunes) { return "", errors.New("slice bounds out of range")}
- return string(asRunes[startEnd[0]:startEnd[1]]), nil
- } else if len(startEnd) == 1 {- return string(asRunes[startEnd[0]:]), nil
+ return string(asRunes[argStart:argEnd]), nil
+ } else if argNum == 1 {+ return string(asRunes[argStart:]), nil
} else {return string(asRunes[:]), nil
}
@@ -179,22 +212,6 @@
}
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)
- }
- }
asRunes := []rune(aStr)
--- a/tpl/template_funcs_test.go
+++ b/tpl/template_funcs_test.go
@@ -348,29 +348,46 @@
}
func TestSlicestr(t *testing.T) {+ var err error
for i, this := range []struct { v1 interface{}- v2 []int
+ v2 interface{}+ v3 interface{} expect interface{} }{- {"abc", []int{1, 2}, "b"},- {"abc", []int{1, 3}, "bc"},- {"abc", []int{0, 1}, "a"},- {"abcdef", []int{}, "abcdef"},- {"abcdef", []int{0, 6}, "abcdef"},- {"abcdef", []int{0, 2}, "ab"},- {"abcdef", []int{2}, "cdef"},- {123, []int{1, 3}, "23"},- {123, []int{1, 2, 3}, false},- {"abcdef", []int{6}, false},- {"abcdef", []int{4, 7}, false},- {"abcdef", []int{-1}, false},- {"abcdef", []int{-1, 7}, false},- {"abcdef", []int{1, -1}, false},- {tstNoStringer{}, []int{0, 1}, false},- {"ĀĀĀ", []int{0, 1}, "Ā"}, // issue #1333+ {"abc", 1, 2, "b"},+ {"abc", 1, 3, "bc"},+ {"abcdef", 1, int8(3), "bc"},+ {"abcdef", 1, int16(3), "bc"},+ {"abcdef", 1, int32(3), "bc"},+ {"abcdef", 1, int64(3), "bc"},+ {"abc", 0, 1, "a"},+ {"abcdef", nil, nil, "abcdef"},+ {"abcdef", 0, 6, "abcdef"},+ {"abcdef", 0, 2, "ab"},+ {"abcdef", 2, nil, "cdef"},+ {"abcdef", int8(2), nil, "cdef"},+ {"abcdef", int16(2), nil, "cdef"},+ {"abcdef", int32(2), nil, "cdef"},+ {"abcdef", int64(2), nil, "cdef"},+ {123, 1, 3, "23"},+ {"abcdef", 6, nil, false},+ {"abcdef", 4, 7, false},+ {"abcdef", -1, nil, false},+ {"abcdef", -1, 7, false},+ {"abcdef", 1, -1, false},+ {tstNoStringer{}, 0, 1, false},+ {"ĀĀĀ", 0, 1, "Ā"}, // issue #1333 } {- result, err := Slicestr(this.v1, this.v2...)
+
+ var result string
+ if this.v2 == nil {+ result, err = Slicestr(this.v1)
+ } else if this.v3 == nil {+ result, err = Slicestr(this.v1, this.v2)
+ } else {+ result, err = Slicestr(this.v1, this.v2, this.v3)
+ }
if b, ok := this.expect.(bool); ok && !b { if err == nil {--
⑨