Slicestr fix for other int type param
authorBenny Wu <benzwu@gmail.com>
Fri, 14 Aug 2015 08:36:56 +0000 (15:36 +0700)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Fri, 14 Aug 2015 15:26:30 +0000 (17:26 +0200)
Fixes #1347

tpl/template_funcs.go
tpl/template_funcs_test.go

index d26dc6494707ed0a5f1566d6393e98936ed95c01..4b9f7011198a4d5aebc97fa94ffc6d35cd09125f 100644 (file)
@@ -128,32 +128,65 @@ func compareGetFloat(a interface{}, b interface{}) (float64, float64) {
        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 @@ func Substr(a interface{}, nums ...interface{}) (string, error) {
        }
 
        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)
 
index d86eeba1c544cecd250c972b2b4bb665fe245097..585702ae7554d2e8ea220d5e962d76cee49911fd 100644 (file)
@@ -348,29 +348,46 @@ func TestIn(t *testing.T) {
 }
 
 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 {