Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add fiber trim functions #91

Merged
merged 1 commit into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,40 @@ Benchmark_ToUpperBytes/fiber-12 25859680 46.43 ns/op
Benchmark_ToUpperBytes/default-12 10015346 117.2 ns/op 80 B/op 1 allocs/op
Benchmark_ToUpperBytes/default-12 10185375 117.8 ns/op 80 B/op 1 allocs/op

Benchmark_TrimRight/fiber-12 522399795 2.138 ns/op 0 B/op 0 allocs/op
Benchmark_TrimRight/fiber-12 578245326 2.084 ns/op 0 B/op 0 allocs/op
Benchmark_TrimRight/default-12 345155300 3.380 ns/op 0 B/op 0 allocs/op
Benchmark_TrimRight/default-12 366972850 3.328 ns/op 0 B/op 0 allocs/op

Benchmark_TrimRightBytes/fiber-12 586471208 2.099 ns/op 0 B/op 0 allocs/op
Benchmark_TrimRightBytes/fiber-12 576055069 2.087 ns/op 0 B/op 0 allocs/op
Benchmark_TrimRightBytes/default-12 348849292 3.316 ns/op 0 B/op 0 allocs/op
Benchmark_TrimRightBytes/default-12 359904445 3.384 ns/op 0 B/op 0 allocs/op

Benchmark_TrimLeft/fiber-12 578044544 2.122 ns/op 0 B/op 0 allocs/op
Benchmark_TrimLeft/fiber-12 585290433 2.074 ns/op 0 B/op 0 allocs/op
Benchmark_TrimLeft/default-12 351906888 3.667 ns/op 0 B/op 0 allocs/op
Benchmark_TrimLeft/default-12 330852666 3.448 ns/op 0 B/op 0 allocs/op

Benchmark_TrimLeftBytes/fiber-12 545400109 2.239 ns/op 0 B/op 0 allocs/op
Benchmark_TrimLeftBytes/fiber-12 544800061 2.270 ns/op 0 B/op 0 allocs/op
Benchmark_TrimLeftBytes/default-12 329749006 3.521 ns/op 0 B/op 0 allocs/op
Benchmark_TrimLeftBytes/default-12 344199560 3.452 ns/op 0 B/op 0 allocs/op

Benchmark_Trim/fiber-12 280692232 4.128 ns/op 0 B/op 0 allocs/op
Benchmark_Trim/fiber-12 297070083 3.961 ns/op 0 B/op 0 allocs/op
Benchmark_Trim/default-12 232522952 5.163 ns/op 0 B/op 0 allocs/op
Benchmark_Trim/default-12 230659057 5.172 ns/op 0 B/op 0 allocs/op
Benchmark_Trim/default.trimspace-12 227328967 5.245 ns/op 0 B/op 0 allocs/op
Benchmark_Trim/default.trimspace-12 227340775 5.253 ns/op 0 B/op 0 allocs/op

Benchmark_TrimBytes/fiber-12 275612090 4.280 ns/op 0 B/op 0 allocs/op
Benchmark_TrimBytes/fiber-12 284892168 4.302 ns/op 0 B/op 0 allocs/op
Benchmark_TrimBytes/default-12 224021550 5.163 ns/op 0 B/op 0 allocs/op
Benchmark_TrimBytes/default-12 239689282 4.922 ns/op 0 B/op 0 allocs/op
Benchmark_TrimBytes/default.trimspace-12 216809300 5.514 ns/op 0 B/op 0 allocs/op
Benchmark_TrimBytes/default.trimspace-12 218177734 5.603 ns/op 0 B/op 0 allocs/op

Benchmark_EqualFoldBytes/fiber-12 22944849 47.14 ns/op 0 B/op 0 allocs/op
Benchmark_EqualFoldBytes/fiber-12 26006342 46.82 ns/op 0 B/op 0 allocs/op
Benchmark_EqualFoldBytes/default-12 5222006 222.5 ns/op 0 B/op 0 allocs/op
Expand Down Expand Up @@ -100,6 +134,7 @@ Benchmark_CalculateTimestamp/fiber-12 1000000000 0.2634 ns/op
Benchmark_CalculateTimestamp/fiber-12 1000000000 0.2935 ns/op 0 B/op 0 allocs/op
Benchmark_CalculateTimestamp/default-12 15740576 73.79 ns/op 0 B/op 0 allocs/op
Benchmark_CalculateTimestamp/default-12 15789036 71.12 ns/op 0 B/op 0 allocs/op

```

See all the benchmarks under https://gofiber.github.io/utils/
35 changes: 35 additions & 0 deletions byteseq.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,38 @@ func EqualFold[S byteSeq](b, s S) bool {
}
return true
}

// TrimLeft is the equivalent of strings/bytes.TrimLeft
func TrimLeft[S byteSeq](s S, cutset byte) S {
lenStr, start := len(s), 0
for start < lenStr && s[start] == cutset {
start++
}
return s[start:]
}

// Trim is the equivalent of strings/bytes.Trim
func Trim[S byteSeq](s S, cutset byte) S {
i, j := 0, len(s)-1
for ; i <= j; i++ {
if s[i] != cutset {
break
}
}
for ; i < j; j-- {
if s[j] != cutset {
break
}
}

return s[i : j+1]
}

// TrimRight is the equivalent of strings/bytes.TrimRight
func TrimRight[S byteSeq](s S, cutset byte) S {
lenStr := len(s)
for lenStr > 0 && s[lenStr-1] == cutset {
lenStr--
}
return s[:lenStr]
}
214 changes: 214 additions & 0 deletions byteseq_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@ func Benchmark_EqualFoldBytes(b *testing.B) {
right := []byte(lowerStr)
var res bool
b.Run("fiber", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = EqualFold(left, right)
}
require.True(b, res)
})
b.Run("default", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = bytes.EqualFold(left, right)
}
Expand All @@ -56,15 +58,227 @@ func Benchmark_EqualFoldBytes(b *testing.B) {
func Benchmark_EqualFold(b *testing.B) {
var res bool
b.Run("fiber", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = EqualFold(upperStr, lowerStr)
}
require.True(b, res)
})
b.Run("default", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = strings.EqualFold(upperStr, lowerStr)
}
require.True(b, res)
})
}

func Test_TrimRight(t *testing.T) {
t.Parallel()
testCases := []struct {
S1 string
S2 string
Cutset byte
}{
{S1: "/test//////", S2: "/test", Cutset: '/'},
{S1: "/test", S2: "/test", Cutset: '/'},
{S1: " ", S2: "", Cutset: ' '},
{S1: " ", S2: "", Cutset: ' '},
{S1: "", S2: "", Cutset: ' '},
}

for _, tc := range testCases {
res := TrimRight(tc.S1, tc.Cutset)
require.Equal(t, tc.S2, res, "string")

resB := TrimRight([]byte(tc.S1), tc.Cutset)
require.Equal(t, []byte(tc.S2), resB, "bytes")
}
}

func Benchmark_TrimRight(b *testing.B) {
var res string
word := "foobar "
expected := "foobar"

b.Run("fiber", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = TrimRight(word, ' ')
}
require.Equal(b, expected, res)
})
b.Run("default", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = strings.TrimRight(word, " ")
}
require.Equal(b, expected, res)
})
}

func Benchmark_TrimRightBytes(b *testing.B) {
var res []byte
word := []byte("foobar ")
expected := []byte("foobar")

b.Run("fiber", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = TrimRight(word, ' ')
}
require.Equal(b, expected, res)
})
b.Run("default", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = bytes.TrimRight(word, " ")
}
require.Equal(b, expected, res)
})
}

func Test_TrimLeft(t *testing.T) {
t.Parallel()
testCases := []struct {
S1 string
S2 string
Cutset byte
}{
{S1: "////test/", S2: "test/", Cutset: '/'},
{S1: "test/", S2: "test/", Cutset: '/'},
{S1: " ", S2: "", Cutset: ' '},
{S1: " ", S2: "", Cutset: ' '},
{S1: "", S2: "", Cutset: ' '},
}

for _, tc := range testCases {
res := TrimLeft(tc.S1, tc.Cutset)
require.Equal(t, tc.S2, res, "string")

resB := TrimLeft([]byte(tc.S1), tc.Cutset)
require.Equal(t, []byte(tc.S2), resB, "bytes")
}
}

func Benchmark_TrimLeft(b *testing.B) {
var res string
word := " foobar"
expected := "foobar"

b.Run("fiber", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = TrimLeft(word, ' ')
}
require.Equal(b, expected, res)
})
b.Run("default", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = strings.TrimLeft(word, " ")
}
require.Equal(b, expected, res)
})
}

func Benchmark_TrimLeftBytes(b *testing.B) {
var res []byte
word := []byte(" foobar")
expected := []byte("foobar")

b.Run("fiber", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = TrimLeft(word, ' ')
}
require.Equal(b, expected, res)
})
b.Run("default", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = bytes.TrimLeft(word, " ")
}
require.Equal(b, expected, res)
})
}

func Test_Trim(t *testing.T) {
t.Parallel()
testCases := []struct {
S1 string
S2 string
Cutset byte
}{
{S1: " test ", S2: "test", Cutset: ' '},
{S1: "test", S2: "test", Cutset: ' '},
{S1: ".test", S2: "test", Cutset: '.'},
{S1: " ", S2: "", Cutset: ' '},
{S1: " ", S2: "", Cutset: ' '},
{S1: "", S2: "", Cutset: ' '},
}

for _, tc := range testCases {
res := Trim(tc.S1, tc.Cutset)
require.Equal(t, tc.S2, res, "string")

resB := Trim([]byte(tc.S1), tc.Cutset)
require.Equal(t, []byte(tc.S2), resB, "bytes")
}
}

func Benchmark_Trim(b *testing.B) {
var res string
word := " foobar "
expected := "foobar"

b.Run("fiber", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = Trim(word, ' ')
}
require.Equal(b, expected, res)
})
b.Run("default", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = strings.Trim(word, " ")
}
require.Equal(b, expected, res)
})
b.Run("default.trimspace", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = strings.TrimSpace(word)
}
require.Equal(b, expected, res)
})
}

func Benchmark_TrimBytes(b *testing.B) {
var res []byte
word := []byte(" foobar ")
expected := []byte("foobar")

b.Run("fiber", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = Trim(word, ' ')
}
require.Equal(b, expected, res)
})
b.Run("default", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = bytes.Trim(word, " ")
}
require.Equal(b, expected, res)
})
b.Run("default.trimspace", func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
res = bytes.TrimSpace(word)
}
require.Equal(b, expected, res)
})
}
Loading