Fix Unicode issue in Slicestr and Substr

Fixes #1333
This commit is contained in:
Bjørn Erik Pedersen 2015-08-07 08:52:22 +02:00
parent de7dd70bbc
commit c7aa881d90
2 changed files with 22 additions and 16 deletions

View file

@ -141,19 +141,21 @@ func Slicestr(a interface{}, startEnd ...int) (string, error) {
return "", errors.New("too many arguments") return "", errors.New("too many arguments")
} }
if len(startEnd) > 0 && (startEnd[0] < 0 || startEnd[0] >= len(aStr)) { asRunes := []rune(aStr)
if len(startEnd) > 0 && (startEnd[0] < 0 || startEnd[0] >= len(asRunes)) {
return "", errors.New("slice bounds out of range") return "", errors.New("slice bounds out of range")
} }
if len(startEnd) == 2 { if len(startEnd) == 2 {
if startEnd[1] < 0 || startEnd[1] > len(aStr) { if startEnd[1] < 0 || startEnd[1] > len(asRunes) {
return "", errors.New("slice bounds out of range") return "", errors.New("slice bounds out of range")
} }
return aStr[startEnd[0]:startEnd[1]], nil return string(asRunes[startEnd[0]:startEnd[1]]), nil
} else if len(startEnd) == 1 { } else if len(startEnd) == 1 {
return aStr[startEnd[0]:], nil return string(asRunes[startEnd[0]:]), nil
} else { } else {
return aStr[:], nil return string(asRunes[:]), nil
} }
} }
@ -194,6 +196,8 @@ func Substr(a interface{}, nums ...interface{}) (string, error) {
} }
} }
asRunes := []rune(aStr)
switch len(nums) { switch len(nums) {
case 0: case 0:
return "", errors.New("too less arguments") return "", errors.New("too less arguments")
@ -201,7 +205,7 @@ func Substr(a interface{}, nums ...interface{}) (string, error) {
if start, err = toInt(nums[0], "start argument must be integer"); err != nil { if start, err = toInt(nums[0], "start argument must be integer"); err != nil {
return "", err return "", err
} }
length = len(aStr) length = len(asRunes)
case 2: case 2:
if start, err = toInt(nums[0], "start argument must be integer"); err != nil { if start, err = toInt(nums[0], "start argument must be integer"); err != nil {
return "", err return "", err
@ -213,10 +217,10 @@ func Substr(a interface{}, nums ...interface{}) (string, error) {
return "", errors.New("too many arguments") return "", errors.New("too many arguments")
} }
if start < -len(aStr) { if start < -len(asRunes) {
start = 0 start = 0
} }
if start > len(aStr) { if start > len(asRunes) {
return "", errors.New(fmt.Sprintf("start position out of bounds for %d-byte string", len(aStr))) return "", errors.New(fmt.Sprintf("start position out of bounds for %d-byte string", len(aStr)))
} }
@ -225,24 +229,24 @@ func Substr(a interface{}, nums ...interface{}) (string, error) {
s = start s = start
e = start + length e = start + length
} else if start < 0 && length >= 0 { } else if start < 0 && length >= 0 {
s = len(aStr) + start - length + 1 s = len(asRunes) + start - length + 1
e = len(aStr) + start + 1 e = len(asRunes) + start + 1
} else if start >= 0 && length < 0 { } else if start >= 0 && length < 0 {
s = start s = start
e = len(aStr) + length e = len(asRunes) + length
} else { } else {
s = len(aStr) + start s = len(asRunes) + start
e = len(aStr) + length e = len(asRunes) + length
} }
if s > e { if s > e {
return "", errors.New(fmt.Sprintf("calculated start position greater than end position: %d > %d", s, e)) return "", errors.New(fmt.Sprintf("calculated start position greater than end position: %d > %d", s, e))
} }
if e > len(aStr) { if e > len(asRunes) {
e = len(aStr) e = len(asRunes)
} }
return aStr[s:e], nil return string(asRunes[s:e]), nil
} }

View file

@ -368,6 +368,7 @@ func TestSlicestr(t *testing.T) {
{"abcdef", []int{-1, 7}, false}, {"abcdef", []int{-1, 7}, false},
{"abcdef", []int{1, -1}, false}, {"abcdef", []int{1, -1}, false},
{tstNoStringer{}, []int{0, 1}, false}, {tstNoStringer{}, []int{0, 1}, false},
{"ĀĀĀ", []int{0, 1}, "Ā"}, // issue #1333
} { } {
result, err := Slicestr(this.v1, this.v2...) result, err := Slicestr(this.v1, this.v2...)
@ -422,6 +423,7 @@ func TestSubstr(t *testing.T) {
{"abcdef", 2.0, nil, false}, {"abcdef", 2.0, nil, false},
{"abcdef", 2.0, 2, false}, {"abcdef", 2.0, 2, false},
{"abcdef", 2, 2.0, false}, {"abcdef", 2, 2.0, false},
{"ĀĀĀ", 1, 2, "ĀĀ"}, // # issue 1333
} { } {
var result string var result string
n = i n = i