mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
add function SubStrRune/StrLimitRune/PosRune/PosIRune/PosRRune/PosRIRune for package gstr; remove unicode support in function SubStr/StrLimit for package gstr
This commit is contained in:
@ -158,9 +158,35 @@ func IsNumeric(s string) bool {
|
||||
|
||||
// SubStr returns a portion of string <str> specified by the <start> and <length> parameters.
|
||||
func SubStr(str string, start int, length ...int) (substr string) {
|
||||
lth := len(str)
|
||||
|
||||
// Simple border checks.
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
if start >= lth {
|
||||
start = lth
|
||||
}
|
||||
end := lth
|
||||
if len(length) > 0 {
|
||||
end = start + length[0]
|
||||
if end < start {
|
||||
end = lth
|
||||
}
|
||||
}
|
||||
if end > lth {
|
||||
end = lth
|
||||
}
|
||||
return str[start:end]
|
||||
}
|
||||
|
||||
// SubStrRune returns a portion of string <str> specified by the <start> and <length> parameters.
|
||||
// SubStrRune considers parameter <str> as unicode string.
|
||||
func SubStrRune(str string, start int, length ...int) (substr string) {
|
||||
// Converting to []rune to support unicode.
|
||||
rs := []rune(str)
|
||||
lth := len(rs)
|
||||
|
||||
// Simple border checks.
|
||||
if start < 0 {
|
||||
start = 0
|
||||
@ -181,10 +207,23 @@ func SubStr(str string, start int, length ...int) (substr string) {
|
||||
return string(rs[start:end])
|
||||
}
|
||||
|
||||
// StrLimit returns a portion of string <str> specified by <length> parameters,
|
||||
// if the length of <str> is greater than <length>,
|
||||
// then the <suffix> will be appended to the result string.
|
||||
// StrLimit returns a portion of string <str> specified by <length> parameters, if the length
|
||||
// of <str> is greater than <length>, then the <suffix> will be appended to the result string.
|
||||
func StrLimit(str string, length int, suffix ...string) string {
|
||||
if len(str) < length {
|
||||
return str
|
||||
}
|
||||
addStr := "..."
|
||||
if len(suffix) > 0 {
|
||||
addStr = suffix[0]
|
||||
}
|
||||
return str[0:length] + addStr
|
||||
}
|
||||
|
||||
// StrLimitRune returns a portion of string <str> specified by <length> parameters, if the length
|
||||
// of <str> is greater than <length>, then the <suffix> will be appended to the result string.
|
||||
// StrLimitRune considers parameter <str> as unicode string.
|
||||
func StrLimitRune(str string, length int, suffix ...string) string {
|
||||
rs := []rune(str)
|
||||
if len(rs) < length {
|
||||
return str
|
||||
@ -255,6 +294,7 @@ func NumberFormat(number float64, decimals int, decPoint, thousandsSep string) s
|
||||
// Can be used to split a string into smaller chunks which is useful for
|
||||
// e.g. converting BASE64 string output to match RFC 2045 semantics.
|
||||
// It inserts end every chunkLen characters.
|
||||
// It considers parameter <body> and <end> as unicode string.
|
||||
func ChunkSplit(body string, chunkLen int, end string) string {
|
||||
if end == "" {
|
||||
end = "\r\n"
|
||||
@ -304,6 +344,7 @@ func HasSuffix(s, suffix string) bool {
|
||||
}
|
||||
|
||||
// CountWords returns information about words' count used in a string.
|
||||
// It considers parameter <str> as unicode string.
|
||||
func CountWords(str string) map[string]int {
|
||||
m := make(map[string]int)
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
@ -324,6 +365,7 @@ func CountWords(str string) map[string]int {
|
||||
}
|
||||
|
||||
// CountChars returns information about chars' count used in a string.
|
||||
// It considers parameter <str> as unicode string.
|
||||
func CountChars(str string, noSpace ...bool) map[string]int {
|
||||
m := make(map[string]int)
|
||||
countSpace := true
|
||||
@ -423,6 +465,7 @@ func Str(haystack string, needle string) string {
|
||||
}
|
||||
|
||||
// Shuffle randomly shuffles a string.
|
||||
// It considers parameter <str> as unicode string.
|
||||
func Shuffle(str string) string {
|
||||
runes := []rune(str)
|
||||
s := make([]rune, len(runes))
|
||||
@ -502,19 +545,22 @@ func Ord(char string) int {
|
||||
}
|
||||
|
||||
// HideStr replaces part of the the string <str> to <hide> by <percentage> from the <middle>.
|
||||
// It considers parameter <str> as unicode string.
|
||||
func HideStr(str string, percent int, hide string) string {
|
||||
array := strings.Split(str, "@")
|
||||
if len(array) > 1 {
|
||||
str = array[0]
|
||||
}
|
||||
rs := []rune(str)
|
||||
length := len(rs)
|
||||
mid := math.Floor(float64(length / 2))
|
||||
hideLen := int(math.Floor(float64(length) * (float64(percent) / 100)))
|
||||
start := int(mid - math.Floor(float64(hideLen)/2))
|
||||
hideStr := []rune("")
|
||||
hideRune := []rune(hide)
|
||||
for i := 0; i < int(hideLen); i++ {
|
||||
var (
|
||||
rs = []rune(str)
|
||||
length = len(rs)
|
||||
mid = math.Floor(float64(length / 2))
|
||||
hideLen = int(math.Floor(float64(length) * (float64(percent) / 100)))
|
||||
start = int(mid - math.Floor(float64(hideLen)/2))
|
||||
hideStr = []rune("")
|
||||
hideRune = []rune(hide)
|
||||
)
|
||||
for i := 0; i < hideLen; i++ {
|
||||
hideStr = append(hideStr, hideRune...)
|
||||
}
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
@ -529,6 +575,7 @@ func HideStr(str string, percent int, hide string) string {
|
||||
|
||||
// Nl2Br inserts HTML line breaks(<br>|<br />) before all newlines in a string:
|
||||
// \n\r, \r\n, \r, \n.
|
||||
// It considers parameter <str> as unicode string.
|
||||
func Nl2Br(str string, isXhtml ...bool) string {
|
||||
r, n, runes := '\r', '\n', []rune(str)
|
||||
var br []byte
|
||||
|
||||
@ -31,6 +31,15 @@ func Pos(haystack, needle string, startOffset ...int) int {
|
||||
return pos + offset
|
||||
}
|
||||
|
||||
// PosRune acts like function Pos but considers <haystack> and <needle> as unicode string.
|
||||
func PosRune(haystack, needle string, startOffset ...int) int {
|
||||
pos := Pos(haystack, needle, startOffset...)
|
||||
if pos < 3 {
|
||||
return pos
|
||||
}
|
||||
return len([]rune(haystack[:pos]))
|
||||
}
|
||||
|
||||
// PosI returns the position of the first occurrence of <needle>
|
||||
// in <haystack> from <startOffset>, case-insensitively.
|
||||
// It returns -1, if not found.
|
||||
@ -54,6 +63,15 @@ func PosI(haystack, needle string, startOffset ...int) int {
|
||||
return pos + offset
|
||||
}
|
||||
|
||||
// PosIRune acts like function PosI but considers <haystack> and <needle> as unicode string.
|
||||
func PosIRune(haystack, needle string, startOffset ...int) int {
|
||||
pos := PosI(haystack, needle, startOffset...)
|
||||
if pos < 3 {
|
||||
return pos
|
||||
}
|
||||
return len([]rune(haystack[:pos]))
|
||||
}
|
||||
|
||||
// PosR returns the position of the last occurrence of <needle>
|
||||
// in <haystack> from <startOffset>, case-sensitively.
|
||||
// It returns -1, if not found.
|
||||
@ -79,6 +97,15 @@ func PosR(haystack, needle string, startOffset ...int) int {
|
||||
return pos
|
||||
}
|
||||
|
||||
// PosRRune acts like function PosR but considers <haystack> and <needle> as unicode string.
|
||||
func PosRRune(haystack, needle string, startOffset ...int) int {
|
||||
pos := PosR(haystack, needle, startOffset...)
|
||||
if pos < 3 {
|
||||
return pos
|
||||
}
|
||||
return len([]rune(haystack[:pos]))
|
||||
}
|
||||
|
||||
// PosRI returns the position of the last occurrence of <needle>
|
||||
// in <haystack> from <startOffset>, case-insensitively.
|
||||
// It returns -1, if not found.
|
||||
@ -103,3 +130,12 @@ func PosRI(haystack, needle string, startOffset ...int) int {
|
||||
}
|
||||
return pos
|
||||
}
|
||||
|
||||
// PosRIRune acts like function PosRI but considers <haystack> and <needle> as unicode string.
|
||||
func PosRIRune(haystack, needle string, startOffset ...int) int {
|
||||
pos := PosRI(haystack, needle, startOffset...)
|
||||
if pos < 3 {
|
||||
return pos
|
||||
}
|
||||
return len([]rune(haystack[:pos]))
|
||||
}
|
||||
|
||||
@ -137,23 +137,43 @@ func Test_IsNumeric(t *testing.T) {
|
||||
func Test_SubStr(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
t.Assert(gstr.SubStr("我爱GoFrame", 0), "我爱GoFrame")
|
||||
t.Assert(gstr.SubStr("我爱GoFrame", 2), "GoFrame")
|
||||
t.Assert(gstr.SubStr("我爱GoFrame", 2, 2), "Go")
|
||||
t.Assert(gstr.SubStr("我爱GoFrame", 6), "GoFrame")
|
||||
t.Assert(gstr.SubStr("我爱GoFrame", 6, 2), "Go")
|
||||
t.Assert(gstr.SubStr("我爱GoFrame", -1, 30), "我爱GoFrame")
|
||||
t.Assert(gstr.SubStr("我爱GoFrame", 30, 30), "")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_SubStrRune(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
t.Assert(gstr.SubStrRune("我爱GoFrame", 0), "我爱GoFrame")
|
||||
t.Assert(gstr.SubStrRune("我爱GoFrame", 2), "GoFrame")
|
||||
t.Assert(gstr.SubStrRune("我爱GoFrame", 2, 2), "Go")
|
||||
t.Assert(gstr.SubStrRune("我爱GoFrame", -1, 30), "我爱GoFrame")
|
||||
t.Assert(gstr.SubStrRune("我爱GoFrame", 30, 30), "")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_StrLimit(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
t.Assert(gstr.StrLimit("我爱GoFrame", 2), "我爱...")
|
||||
t.Assert(gstr.StrLimit("我爱GoFrame", 2, ""), "我爱")
|
||||
t.Assert(gstr.StrLimit("我爱GoFrame", 2, "**"), "我爱**")
|
||||
t.Assert(gstr.StrLimit("我爱GoFrame", 4, ""), "我爱Go")
|
||||
t.Assert(gstr.StrLimit("我爱GoFrame", 6), "我爱...")
|
||||
t.Assert(gstr.StrLimit("我爱GoFrame", 6, ""), "我爱")
|
||||
t.Assert(gstr.StrLimit("我爱GoFrame", 6, "**"), "我爱**")
|
||||
t.Assert(gstr.StrLimit("我爱GoFrame", 8, ""), "我爱Go")
|
||||
t.Assert(gstr.StrLimit("*", 4, ""), "*")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_StrLimitRune(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
t.Assert(gstr.StrLimitRune("我爱GoFrame", 2), "我爱...")
|
||||
t.Assert(gstr.StrLimitRune("我爱GoFrame", 2, ""), "我爱")
|
||||
t.Assert(gstr.StrLimitRune("我爱GoFrame", 2, "**"), "我爱**")
|
||||
t.Assert(gstr.StrLimitRune("我爱GoFrame", 4, ""), "我爱Go")
|
||||
t.Assert(gstr.StrLimitRune("*", 4, ""), "*")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_HasPrefix(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
t.Assert(gstr.HasPrefix("我爱GoFrame", "我爱"), true)
|
||||
|
||||
@ -23,6 +23,28 @@ func Test_Pos(t *testing.T) {
|
||||
t.Assert(gstr.Pos(s1, "abd", 0), -1)
|
||||
t.Assert(gstr.Pos(s1, "e", -4), 11)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
s1 := "我爱China very much"
|
||||
t.Assert(gstr.Pos(s1, "爱"), 3)
|
||||
t.Assert(gstr.Pos(s1, "C"), 6)
|
||||
t.Assert(gstr.Pos(s1, "China"), 6)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_PosRune(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
s1 := "abcdEFGabcdefg"
|
||||
t.Assert(gstr.PosRune(s1, "ab"), 0)
|
||||
t.Assert(gstr.PosRune(s1, "ab", 2), 7)
|
||||
t.Assert(gstr.PosRune(s1, "abd", 0), -1)
|
||||
t.Assert(gstr.PosRune(s1, "e", -4), 11)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
s1 := "我爱China very much"
|
||||
t.Assert(gstr.PosRune(s1, "爱"), 1)
|
||||
t.Assert(gstr.PosRune(s1, "C"), 2)
|
||||
t.Assert(gstr.PosRune(s1, "China"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_PosI(t *testing.T) {
|
||||
@ -34,6 +56,29 @@ func Test_PosI(t *testing.T) {
|
||||
t.Assert(gstr.PosI(s1, "abd", 0), -1)
|
||||
t.Assert(gstr.PosI(s1, "E", -4), 11)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
s1 := "我爱China very much"
|
||||
t.Assert(gstr.PosI(s1, "爱"), 3)
|
||||
t.Assert(gstr.PosI(s1, "c"), 6)
|
||||
t.Assert(gstr.PosI(s1, "china"), 6)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_PosIRune(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
s1 := "abcdEFGabcdefg"
|
||||
t.Assert(gstr.PosIRune(s1, "zz"), -1)
|
||||
t.Assert(gstr.PosIRune(s1, "ab"), 0)
|
||||
t.Assert(gstr.PosIRune(s1, "ef", 2), 4)
|
||||
t.Assert(gstr.PosIRune(s1, "abd", 0), -1)
|
||||
t.Assert(gstr.PosIRune(s1, "E", -4), 11)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
s1 := "我爱China very much"
|
||||
t.Assert(gstr.PosIRune(s1, "爱"), 1)
|
||||
t.Assert(gstr.PosIRune(s1, "c"), 2)
|
||||
t.Assert(gstr.PosIRune(s1, "china"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_PosR(t *testing.T) {
|
||||
@ -47,6 +92,31 @@ func Test_PosR(t *testing.T) {
|
||||
t.Assert(gstr.PosR(s1, "abd", 0), -1)
|
||||
t.Assert(gstr.PosR(s1, "e", -4), -1)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
s1 := "我爱China very much"
|
||||
t.Assert(gstr.PosR(s1, "爱"), 3)
|
||||
t.Assert(gstr.PosR(s1, "C"), 6)
|
||||
t.Assert(gstr.PosR(s1, "China"), 6)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_PosRRune(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
s1 := "abcdEFGabcdefg"
|
||||
s2 := "abcdEFGz1cdeab"
|
||||
t.Assert(gstr.PosRRune(s1, "zz"), -1)
|
||||
t.Assert(gstr.PosRRune(s1, "ab"), 7)
|
||||
t.Assert(gstr.PosRRune(s2, "ab", -2), 0)
|
||||
t.Assert(gstr.PosRRune(s1, "ef"), 11)
|
||||
t.Assert(gstr.PosRRune(s1, "abd", 0), -1)
|
||||
t.Assert(gstr.PosRRune(s1, "e", -4), -1)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
s1 := "我爱China very much"
|
||||
t.Assert(gstr.PosRRune(s1, "爱"), 1)
|
||||
t.Assert(gstr.PosRRune(s1, "C"), 2)
|
||||
t.Assert(gstr.PosRRune(s1, "China"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_PosRI(t *testing.T) {
|
||||
@ -60,4 +130,29 @@ func Test_PosRI(t *testing.T) {
|
||||
t.Assert(gstr.PosRI(s1, "abd", 0), -1)
|
||||
t.Assert(gstr.PosRI(s1, "e", -5), 4)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
s1 := "我爱China very much"
|
||||
t.Assert(gstr.PosRI(s1, "爱"), 3)
|
||||
t.Assert(gstr.PosRI(s1, "C"), 19)
|
||||
t.Assert(gstr.PosRI(s1, "China"), 6)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_PosRIRune(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
s1 := "abcdEFGabcdefg"
|
||||
s2 := "abcdEFGz1cdeab"
|
||||
t.Assert(gstr.PosRIRune(s1, "zz"), -1)
|
||||
t.Assert(gstr.PosRIRune(s1, "AB"), 7)
|
||||
t.Assert(gstr.PosRIRune(s2, "AB", -2), 0)
|
||||
t.Assert(gstr.PosRIRune(s1, "EF"), 11)
|
||||
t.Assert(gstr.PosRIRune(s1, "abd", 0), -1)
|
||||
t.Assert(gstr.PosRIRune(s1, "e", -5), 4)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
s1 := "我爱China very much"
|
||||
t.Assert(gstr.PosRIRune(s1, "爱"), 1)
|
||||
t.Assert(gstr.PosRIRune(s1, "C"), 15)
|
||||
t.Assert(gstr.PosRIRune(s1, "China"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user