mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-23 08:48:32 +02:00
small string split join optimization
This commit is contained in:
@@ -193,7 +193,7 @@ func Deserialize(src SerializedObject, dst any) E.Error {
|
||||
for _, field := range fields {
|
||||
var key string
|
||||
if jsonTag, ok := field.Tag.Lookup("json"); ok {
|
||||
key = strings.Split(jsonTag, ",")[0]
|
||||
key = strutils.CommaSeperatedList(jsonTag)[0]
|
||||
} else {
|
||||
key = field.Name
|
||||
}
|
||||
@@ -208,7 +208,7 @@ func Deserialize(src SerializedObject, dst any) E.Error {
|
||||
|
||||
aliases, ok := field.Tag.Lookup("aliases")
|
||||
if ok {
|
||||
for _, alias := range strings.Split(aliases, ",") {
|
||||
for _, alias := range strutils.CommaSeperatedList(aliases) {
|
||||
mapping[alias] = dstV.FieldByName(field.Name)
|
||||
fieldName[field.Name] = alias
|
||||
}
|
||||
@@ -425,7 +425,7 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr E.E
|
||||
lines := []string{}
|
||||
src = strings.TrimSpace(src)
|
||||
if src != "" {
|
||||
lines = strings.Split(src, "\n")
|
||||
lines = strutils.SplitLine(src)
|
||||
for i := range lines {
|
||||
lines[i] = strings.TrimSpace(lines[i])
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package strutils
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/yusing/go-proxy/internal/logging"
|
||||
)
|
||||
|
||||
type Parser interface {
|
||||
@@ -22,7 +20,7 @@ func Parse[T Parser](from string) (t T, err error) {
|
||||
func MustParse[T Parser](from string) T {
|
||||
t, err := Parse[T](from)
|
||||
if err != nil {
|
||||
logging.Panic().Err(err).Msg("must failed")
|
||||
panic("must failed: " + err.Error())
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
81
internal/utils/strutils/split_join.go
Normal file
81
internal/utils/strutils/split_join.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package strutils
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SplitRune is like strings.Split but takes a rune as separator.
|
||||
func SplitRune(s string, sep rune) []string {
|
||||
if sep == 0 {
|
||||
return strings.Split(s, "")
|
||||
}
|
||||
n := strings.Count(s, string(sep)) + 1
|
||||
if n > len(s)+1 {
|
||||
n = len(s) + 1
|
||||
}
|
||||
a := make([]string, n)
|
||||
n--
|
||||
i := 0
|
||||
for i < n {
|
||||
m := strings.IndexRune(s, sep)
|
||||
if m < 0 {
|
||||
break
|
||||
}
|
||||
a[i] = s[:m]
|
||||
s = s[m+1:]
|
||||
i++
|
||||
}
|
||||
a[i] = s
|
||||
return a[:i+1]
|
||||
}
|
||||
|
||||
// SplitComma is a wrapper around SplitRune(s, ',').
|
||||
func SplitComma(s string) []string {
|
||||
return SplitRune(s, ',')
|
||||
}
|
||||
|
||||
// SplitLine is a wrapper around SplitRune(s, '\n').
|
||||
func SplitLine(s string) []string {
|
||||
return SplitRune(s, '\n')
|
||||
}
|
||||
|
||||
// SplitSpace is a wrapper around SplitRune(s, ' ').
|
||||
func SplitSpace(s string) []string {
|
||||
return SplitRune(s, ' ')
|
||||
}
|
||||
|
||||
// JoinRune is like strings.Join but takes a rune as separator.
|
||||
func JoinRune(elems []string, sep rune) string {
|
||||
switch len(elems) {
|
||||
case 0:
|
||||
return ""
|
||||
case 1:
|
||||
return elems[0]
|
||||
}
|
||||
if sep == 0 {
|
||||
return strings.Join(elems, "")
|
||||
}
|
||||
|
||||
var n int
|
||||
for _, elem := range elems {
|
||||
if len(elem) > math.MaxInt-n {
|
||||
panic("strings: Join output length overflow")
|
||||
}
|
||||
n += len(elem)
|
||||
}
|
||||
|
||||
var b strings.Builder
|
||||
b.Grow(n)
|
||||
b.WriteString(elems[0])
|
||||
for _, s := range elems[1:] {
|
||||
b.WriteRune(sep)
|
||||
b.WriteString(s)
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// JoinLines is a wrapper around JoinRune(elems, '\n').
|
||||
func JoinLines(elems []string) string {
|
||||
return JoinRune(elems, '\n')
|
||||
}
|
||||
38
internal/utils/strutils/split_join_test.go
Normal file
38
internal/utils/strutils/split_join_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package strutils_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
. "github.com/yusing/go-proxy/internal/utils/strutils"
|
||||
. "github.com/yusing/go-proxy/internal/utils/testing"
|
||||
)
|
||||
|
||||
var alphaNumeric = func() string {
|
||||
var s strings.Builder
|
||||
for i := range 'z' - 'a' + 1 {
|
||||
s.WriteRune('a' + i)
|
||||
s.WriteRune('A' + i)
|
||||
s.WriteRune(',')
|
||||
}
|
||||
for i := range '9' - '0' + 1 {
|
||||
s.WriteRune('0' + i)
|
||||
s.WriteRune(',')
|
||||
}
|
||||
return s.String()
|
||||
}()
|
||||
|
||||
func TestSplit(t *testing.T) {
|
||||
tests := map[string]rune{
|
||||
"": 0,
|
||||
"1": '1',
|
||||
",": ',',
|
||||
}
|
||||
for sep, rsep := range tests {
|
||||
t.Run(sep, func(t *testing.T) {
|
||||
expected := strings.Split(alphaNumeric, sep)
|
||||
ExpectDeepEqual(t, SplitRune(alphaNumeric, rsep), expected)
|
||||
ExpectEqual(t, JoinRune(expected, rsep), alphaNumeric)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,7 @@
|
||||
package strutils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
E "github.com/yusing/go-proxy/internal/error"
|
||||
)
|
||||
|
||||
func Atoi(s string) (int, E.Error) {
|
||||
val, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return val, E.From(errors.Unwrap(err)).Subject(s)
|
||||
}
|
||||
|
||||
return val, nil
|
||||
}
|
||||
var Atoi = strconv.Atoi
|
||||
|
||||
@@ -8,8 +8,10 @@ import (
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// CommaSeperatedList returns a list of strings split by commas,
|
||||
// then trim spaces from each element.
|
||||
func CommaSeperatedList(s string) []string {
|
||||
res := strings.Split(s, ",")
|
||||
res := SplitComma(s)
|
||||
for i, part := range res {
|
||||
res[i] = strings.TrimSpace(part)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user