1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00

refactor: refact some strutil functions

This commit is contained in:
dudaodong
2025-04-21 14:07:52 +08:00
parent d88bba07dd
commit 0b5dc86d70
4 changed files with 121 additions and 121 deletions

View File

@@ -1,51 +1,51 @@
-----BEGIN rsa private key----- -----BEGIN rsa private key-----
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
-----END rsa private key----- -----END rsa private key-----

View File

@@ -1,14 +1,14 @@
-----BEGIN rsa public key----- -----BEGIN rsa public key-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtKEukXkdl8ggX5I5Us0M MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2yy8VWqASCh7YbtiJiWt
BcsrFzbTgwOn8u72IhJzruvsHcjlGGF5L1eXh3C0zbcoWq+Bxf8NnXvSXASZlZHT SimACGycqUgYOiaR1SR6F2rK7Xe3juHUuqI5RVZyo69Jh24jYYNgkS05XtJrmykN
iSVLFerxFw2LwTNcyfOz/Y/wIbtrYu4ZdttLKdJS607UvnZ57O7SQni5rxYAP5j+ jGXxtaOnLYFy+UQmor3BtgVkDKxGL4hHnGdnHIaU/btSNd0ewvYMAg/9sVK75o8Z
veKHEJgAO7Sn0lEEWwkeudsfVrQmQx6JHYtCtx78p2GHXPj9wXWHxWHKMkczKtmB /4XH14iTZlLpohRaKZf7nvN5ecRaNs/eItgzUy43b2rYdIxTFDjqF1x/LIQcrb3c
FDLlYocPhQfWzx87sYKjGmTMGzVddsrllAqVozlxXTQndOdozx8BWHSBiYWguOvW 6oDjGd6WwR0sEQL47EgTYNo9pbbULZ1X7h1pS9hNdAEcwZEo78TsBScQ7tPL2G1L
iYjvryrIf0B7wn4wt3o2Yre3w4BkwrTUE73JWG2q1NLuPoT27m7WcdVFGGcKAygA 4PA6oxid/nOXwkJNHMv1HcZZEj6uZSgv1BP+rGWxTY0z8o+EDFR1lq3lAgc4cC2h
dMMSwS530v8tnAw876/w1SfUmtkIcqknysMjsvxHx1fbEfkl3b0yBnzcUrT1qxzm MsnQ7AIqhQe4vH0Gh0W+sdccuIlV0H8RDMcz9px45unqWKBo5dE7Iyqyr46j8r9w
NEqJSQXBtFYFyGgyeL8J1ul/T5hPSNz0we5TO/xRkX5Y1HNJ+a2r8EnE1PU8zgQG FUUWxN7Gvh45OgRyPYs4C6BEFgyTtJnff/T9e7d7RQEKXt4Dr3fqFztbgogJwxi8
BxYSIub4ajSUccyn5yHQ/k2FlsolZiu/UzfnzMgdg55svgf5x1ntKYBoVHuYe84A ZpZ5CvKRO39V/YorGrGBi1cVLR8opTp7N9+pzwkZpgfh3JHZeDreEAnU8tfwu/9u
b3WRAeVlUi0OphvFlBzfIQvrG2sRbiPZRZZ0E8kBH94zPmrFmyX+7TwlSqVHtNFc COPzDKjwrjXOs8tM4WI8ye8uw0DgXAjwqlEvGuWBGOg763zv91vZjJxsHIYr4dSE
+Ynz+hrHcd4z6N7fIb+D1gSYuukkcRqr4ANO0ugZk0YYKaWDf86H7OZOXna8ObIA cJG5tUM0WDETP40uhJj6TZc9iMj9vE0oHmzXPno2K2f+bWHYy3b6ea11VzJVhUu0
i+3gx+Wcp1lm7Ffk9sn+dGkCAwEAAQ== xquay8VYBpMtPYzf74zuMjsCAwEAAQ==
-----END rsa public key----- -----END rsa public key-----

View File

@@ -37,16 +37,17 @@ func CamelCase(s string) string {
// Capitalize converts the first character of a string to upper case and the remaining to lower case. // Capitalize converts the first character of a string to upper case and the remaining to lower case.
// Play: https://go.dev/play/p/2OAjgbmAqHZ // Play: https://go.dev/play/p/2OAjgbmAqHZ
func Capitalize(s string) string { func Capitalize(s string) string {
result := make([]rune, len(s)) if s == "" {
for i, v := range s { return s
if i == 0 {
result[i] = unicode.ToUpper(v)
} else {
result[i] = unicode.ToLower(v)
}
} }
return string(result) runes := []rune(s)
runes[0] = unicode.ToUpper(runes[0])
for i := 1; i < len(runes); i++ {
runes[i] = unicode.ToLower(runes[i])
}
return string(runes)
} }
// UpperFirst converts the first character of string to upper case. // UpperFirst converts the first character of string to upper case.
@@ -127,49 +128,57 @@ func UpperSnakeCase(s string) string {
// Before returns the substring of the source string up to the first occurrence of the specified string. // Before returns the substring of the source string up to the first occurrence of the specified string.
// Play: https://go.dev/play/p/JAWTZDS4F5w // Play: https://go.dev/play/p/JAWTZDS4F5w
func Before(s, char string) string { func Before(s, char string) string {
i := strings.Index(s, char) if char == "" {
if s == "" || char == "" || i == -1 {
return s return s
} }
return s[0:i] if i := strings.Index(s, char); i >= 0 {
return s[:i]
}
return s
} }
// BeforeLast returns the substring of the source string up to the last occurrence of the specified string. // BeforeLast returns the substring of the source string up to the last occurrence of the specified string.
// Play: https://go.dev/play/p/pJfXXAoG_Te // Play: https://go.dev/play/p/pJfXXAoG_Te
func BeforeLast(s, char string) string { func BeforeLast(s, char string) string {
i := strings.LastIndex(s, char) if char == "" {
if s == "" || char == "" || i == -1 {
return s return s
} }
return s[0:i] if i := strings.LastIndex(s, char); i >= 0 {
return s[:i]
}
return s
} }
// After returns the substring after the first occurrence of a specified string in the source string. // After returns the substring after the first occurrence of a specified string in the source string.
// Play: https://go.dev/play/p/RbCOQqCDA7m // Play: https://go.dev/play/p/RbCOQqCDA7m
func After(s, char string) string { func After(s, char string) string {
i := strings.Index(s, char) if char == "" {
if s == "" || char == "" || i == -1 {
return s return s
} }
return s[i+len(char):] if i := strings.Index(s, char); i >= 0 {
return s[i+len(char):]
}
return s
} }
// AfterLast returns the substring after the last occurrence of a specified string in the source string. // AfterLast returns the substring after the last occurrence of a specified string in the source string.
// Play: https://go.dev/play/p/1TegARrb8Yn // Play: https://go.dev/play/p/1TegARrb8Yn
func AfterLast(s, char string) string { func AfterLast(s, char string) string {
i := strings.LastIndex(s, char) if char == "" {
if s == "" || char == "" || i == -1 {
return s return s
} }
return s[i+len(char):] if i := strings.LastIndex(s, char); i >= 0 {
return s[i+len(char):]
}
return s
} }
// IsString check if the value data type is string or not. // IsString check if the value data type is string or not.
@@ -213,20 +222,15 @@ func Wrap(str string, wrapWith string) string {
// Unwrap a given string from anther string. will change source string. // Unwrap a given string from anther string. will change source string.
// Play: https://go.dev/play/p/Ec2q4BzCpG- // Play: https://go.dev/play/p/Ec2q4BzCpG-
func Unwrap(str string, wrapToken string) string { func Unwrap(str string, wrapToken string) string {
if str == "" || wrapToken == "" { if wrapToken == "" || !strings.HasPrefix(str, wrapToken) || !strings.HasSuffix(str, wrapToken) {
return str return str
} }
firstIndex := strings.Index(str, wrapToken) if len(str) < 2*len(wrapToken) {
lastIndex := strings.LastIndex(str, wrapToken) return str
if firstIndex == 0 && lastIndex > 0 && lastIndex <= len(str)-1 {
if len(wrapToken) <= lastIndex {
str = str[len(wrapToken):lastIndex]
}
} }
return str return str[len(wrapToken) : len(str)-len(wrapToken)]
} }
// SplitEx split a given string which can control the result slice contains empty string or not. // SplitEx split a given string which can control the result slice contains empty string or not.
@@ -286,22 +290,21 @@ func Substring(s string, offset int, length uint) string {
size := len(rs) size := len(rs)
if offset < 0 { if offset < 0 {
offset = size + offset offset += size
if offset < 0 { }
offset = 0 if offset < 0 {
} offset = 0
} }
if offset > size { if offset > size {
return "" return ""
} }
if length > uint(size)-uint(offset) { end := offset + int(length)
length = uint(size - offset) if end > size {
end = size
} }
str := string(rs[offset : offset+int(length)]) return strings.ReplaceAll(string(rs[offset:end]), "\x00", "")
return strings.Replace(str, "\x00", "", -1)
} }
// SplitWords splits a string into words, word only contains alphabetic characters. // SplitWords splits a string into words, word only contains alphabetic characters.

View File

@@ -1,6 +1,7 @@
package strutil package strutil
import ( import (
"strings"
"unicode" "unicode"
) )
@@ -111,31 +112,27 @@ func padAtPosition(str string, length int, padStr string, position int) string {
padStr = " " padStr = " "
} }
length = length - len(str) totalPad := length - len(str)
startPadLen := 0 startPad := 0
if position == 0 { if position == 0 {
startPadLen = length / 2 startPad = totalPad / 2
} else if position == 1 { } else if position == 1 {
startPadLen = length startPad = totalPad
} else if position == 2 {
startPad = 0
} }
endPadLen := length - startPadLen endPad := totalPad - startPad
charLen := len(padStr) repeatPad := func(n int) string {
leftPad := "" repeated := strings.Repeat(padStr, (n+len(padStr)-1)/len(padStr))
cur := 0 return repeated[:n]
for cur < startPadLen {
leftPad += string(padStr[cur%charLen])
cur++
} }
cur = 0 left := repeatPad(startPad)
rightPad := "" right := repeatPad(endPad)
for cur < endPadLen {
rightPad += string(padStr[cur%charLen])
cur++
}
return leftPad + str + rightPad return left + str + right
} }
// isLetter checks r is a letter but not CJK character. // isLetter checks r is a letter but not CJK character.