small string split join optimization

This commit is contained in:
yusing
2024-12-19 00:54:31 +08:00
parent 654194b274
commit e7be27413c
20 changed files with 160 additions and 50 deletions

View File

@@ -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
}

View 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')
}

View 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)
})
}
}

View File

@@ -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

View File

@@ -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)
}