Skip to content

Commit

Permalink
refs #18, #9. insert str by rune index; slice supports negative end.
Browse files Browse the repository at this point in the history
  • Loading branch information
huandu committed Jan 9, 2015
1 parent 549ea14 commit 891b276
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 6 deletions.
9 changes: 6 additions & 3 deletions convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ import (
// ToCamelCase can convert all lower case characters behind underscores
// to upper case character.
// Underscore character will be removed in result except following cases.
// * More than 1 underscore, e.g. "a__b" => "A_B"
// * At the beginning of string, e.g. "_a" => "_A"
// * At the end of string, e.g. "ab_" => "Ab_"
// * More than 1 underscore.
// "a__b" => "A_B"
// * At the beginning of string.
// "_a" => "_A"
// * At the end of string.
// "ab_" => "Ab_"
func ToCamelCase(str string) string {
if len(str) == 0 {
return ""
Expand Down
26 changes: 23 additions & 3 deletions manipulate.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,26 @@ func Reverse(str string) string {
}

// Slice a string by rune.
// Start and end must satisfy 0 <= start <= end <= rune length.
//
// Start must satisfy 0 <= start <= rune length.
//
// End can be positive, zero or negative.
// If end >= 0, start and end must satisfy start <= end <= rune length.
// If end < 0, it means slice to the end of string.
//
// Otherwise, Slice will panic as out of range.
func Slice(str string, start, end int) string {
var size, startPos, endPos int

origin := str

if start < 0 || end > len(str) || start > end {
if start < 0 || end > len(str) || (end >= 0 && start > end) {
panic("out of range")
}

end -= start
if end >= 0 {
end -= start
}

for start > 0 && len(str) > 0 {
_, size = utf8.DecodeRuneInString(str)
Expand All @@ -47,6 +55,10 @@ func Slice(str string, start, end int) string {
str = str[size:]
}

if end < 0 {
return origin[startPos:]
}

endPos = startPos

for end > 0 && len(str) > 0 {
Expand Down Expand Up @@ -98,3 +110,11 @@ func LastPartition(str, sep string) []string {

return []string{str[:index], sep, str[index+len(sep):]}
}

// Insert src into dst at given rune index.
// Index is counted by runes instead of bytes.
//
// If index is out of range of dst, panic with out of range.
func Insert(dst, src string, index int) string {
return Slice(dst, 0, index) + src + Slice(dst, index, -1)
}
28 changes: 28 additions & 0 deletions manipulate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ func TestSlice(t *testing.T) {
sep("中en文混~排总是少不了的a", "2", "8"): "n文混~排总",
sep("中en文混~排总是少不了的a", "0", "0"): "",
sep("中en文混~排总是少不了的a", "14", "14"): "",
sep("中en文混~排总是少不了的a", "5", "-1"): "~排总是少不了的a",
sep("中en文混~排总是少不了的a", "14", "-1"): "",

sep("let us slice out of range", "-3", "3"): "out of range",
sep("超出范围哦", "2", "6"): "out of range",
Expand Down Expand Up @@ -86,3 +88,29 @@ func TestLastPartition(t *testing.T) {
sep("来ge混排ba", "e 混"): sep("", "", "来ge混排ba"),
})
}

func TestInsert(t *testing.T) {
InsertRunner := func(str string) (result string) {
defer func() {
if e := recover(); e != nil {
result = e.(string)
}
}()

strs := split(str)
index, _ := strconv.ParseInt(strs[2], 10, 0)
result = Insert(strs[0], strs[1], int(index))
return
}

runTestCases(t, InsertRunner, _M{
sep("abcdefg", "hi", "3"): "abchidefg",
sep("少量中文是必须的", "混pai", "4"): "少量中文混pai是必须的",
sep("zh英文hun排", "~!", "5"): "zh英文h~!un排",
sep("插在begining", "我", "0"): "我插在begining",
sep("插在ending", "我", "8"): "插在ending我",

sep("超tian出yuan边tu界po", "foo", "-1"): "out of range",
sep("超tian出yuan边tu界po", "foo", "17"): "out of range",
})
}

0 comments on commit 891b276

Please sign in to comment.