Skip to content

Commit 2b5b6b2

Browse files
authored
🐛 utils: fix EqualFold and docs (#1833)
* 🔍 utils: add/improve tests for ToLower/ToUpper/EqualFold * 🐛 utils: fix EqualFold and docs
1 parent 2f0d745 commit 2b5b6b2

File tree

4 files changed

+52
-51
lines changed

4 files changed

+52
-51
lines changed

utils/bytes.go

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44

55
package utils
66

7-
// ToLowerBytes is the equivalent of bytes.ToLower
7+
// ToLowerBytes converts ascii slice to lower-case
88
func ToLowerBytes(b []byte) []byte {
99
for i := 0; i < len(b); i++ {
1010
b[i] = toLowerTable[b[i]]
1111
}
1212
return b
1313
}
1414

15-
// ToUpperBytes is the equivalent of bytes.ToUpper
15+
// ToUpperBytes converts ascii slice to upper-case
1616
func ToUpperBytes(b []byte) []byte {
1717
for i := 0; i < len(b); i++ {
1818
b[i] = toUpperTable[b[i]]
@@ -55,16 +55,15 @@ func TrimBytes(b []byte, cutset byte) []byte {
5555
return b[i : j+1]
5656
}
5757

58-
// EqualFold the equivalent of bytes.EqualFold
59-
func EqualFoldBytes(b, s []byte) (equals bool) {
60-
n := len(b)
61-
equals = n == len(s)
62-
if equals {
63-
for i := 0; i < n; i++ {
64-
if equals = b[i]|0x20 == s[i]|0x20; !equals {
65-
break
66-
}
58+
// EqualFoldBytes tests ascii slices for equality case-insensitively
59+
func EqualFoldBytes(b, s []byte) bool {
60+
if len(b) != len(s) {
61+
return false
62+
}
63+
for i := len(b) - 1; i >= 0; i-- {
64+
if toUpperTable[b[i]] != toUpperTable[s[i]] {
65+
return false
6766
}
6867
}
69-
return
68+
return true
7069
}

utils/bytes_test.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ func Test_ToLowerBytes(t *testing.T) {
2424
}
2525

2626
func Benchmark_ToLowerBytes(b *testing.B) {
27-
path := []byte("/RePos/GoFiBer/FibEr/iSsues/187643/CoMmEnts")
27+
path := []byte(largeStr)
28+
want := []byte(lowerStr)
2829
var res []byte
29-
3030
b.Run("fiber", func(b *testing.B) {
3131
for n := 0; n < b.N; n++ {
3232
res = ToLowerBytes(path)
3333
}
34-
AssertEqual(b, bytes.Equal(UnsafeBytes("/repos/gofiber/fiber/issues/187643/comments"), res), true)
34+
AssertEqual(b, bytes.Equal(want, res), true)
3535
})
3636
b.Run("default", func(b *testing.B) {
3737
for n := 0; n < b.N; n++ {
3838
res = bytes.ToLower(path)
3939
}
40-
AssertEqual(b, bytes.Equal(UnsafeBytes("/repos/gofiber/fiber/issues/187643/comments"), res), true)
40+
AssertEqual(b, bytes.Equal(want, res), true)
4141
})
4242
}
4343

@@ -56,20 +56,20 @@ func Test_ToUpperBytes(t *testing.T) {
5656
}
5757

5858
func Benchmark_ToUpperBytes(b *testing.B) {
59-
path := []byte("/RePos/GoFiBer/FibEr/iSsues/187643/CoMmEnts")
59+
path := []byte(largeStr)
60+
want := []byte(upperStr)
6061
var res []byte
61-
6262
b.Run("fiber", func(b *testing.B) {
6363
for n := 0; n < b.N; n++ {
6464
res = ToUpperBytes(path)
6565
}
66-
AssertEqual(b, bytes.Equal(UnsafeBytes("/REPOS/GOFIBER/FIBER/ISSUES/187643/COMMENTS"), res), true)
66+
AssertEqual(b, bytes.Equal(want, res), true)
6767
})
6868
b.Run("default", func(b *testing.B) {
6969
for n := 0; n < b.N; n++ {
7070
res = bytes.ToUpper(path)
7171
}
72-
AssertEqual(b, bytes.Equal(UnsafeBytes("/REPOS/GOFIBER/FIBER/ISSUES/187643/COMMENTS"), res), true)
72+
AssertEqual(b, bytes.Equal(want, res), true)
7373
})
7474
}
7575

@@ -182,10 +182,9 @@ func Benchmark_TrimBytes(b *testing.B) {
182182
}
183183

184184
func Benchmark_EqualFoldBytes(b *testing.B) {
185-
left := []byte("/RePos/GoFiBer/FibEr/iSsues/187643/CoMmEnts")
186-
right := []byte("/RePos/goFiber/Fiber/issues/187643/COMMENTS")
185+
left := []byte(upperStr)
186+
right := []byte(lowerStr)
187187
var res bool
188-
189188
b.Run("fiber", func(b *testing.B) {
190189
for n := 0; n < b.N; n++ {
191190
res = EqualFoldBytes(left, right)
@@ -210,6 +209,8 @@ func Test_EqualFoldBytes(t *testing.T) {
210209
AssertEqual(t, false, res)
211210
res = EqualFoldBytes([]byte("/dddddd"), []byte("eeeeee"))
212211
AssertEqual(t, false, res)
212+
res = EqualFoldBytes([]byte("\na"), []byte("*A"))
213+
AssertEqual(t, false, res)
213214
res = EqualFoldBytes([]byte("/MY3/NAME/IS/:PARAM/*"), []byte("/my3/name/is/:param/*"))
214215
AssertEqual(t, true, res)
215216
res = EqualFoldBytes([]byte("/MY4/NAME/IS/:PARAM/*"), []byte("/my4/nAME/IS/:param/*"))

utils/strings.go

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
package utils
66

7-
// ToLower is the equivalent of strings.ToLower
7+
// ToLower converts ascii string to lower-case
88
func ToLower(b string) string {
99
res := make([]byte, len(b))
1010
copy(res, b)
@@ -15,7 +15,7 @@ func ToLower(b string) string {
1515
return UnsafeString(res)
1616
}
1717

18-
// ToUpper is the equivalent of strings.ToUpper
18+
// ToUpper converts ascii string to upper-case
1919
func ToUpper(b string) string {
2020
res := make([]byte, len(b))
2121
copy(res, b)
@@ -61,16 +61,15 @@ func TrimRight(s string, cutset byte) string {
6161
return s[:lenStr]
6262
}
6363

64-
// EqualFold the equivalent of strings.EqualFold
65-
func EqualFold(b, s string) (equals bool) {
66-
n := len(b)
67-
equals = n == len(s)
68-
if equals {
69-
for i := 0; i < n; i++ {
70-
if equals = b[i]|0x20 == s[i]|0x20; !equals {
71-
break
72-
}
64+
// EqualFold tests ascii strings for equality case-insensitively
65+
func EqualFold(b, s string) bool {
66+
if len(b) != len(s) {
67+
return false
68+
}
69+
for i := len(b) - 1; i >= 0; i-- {
70+
if toUpperTable[b[i]] != toUpperTable[s[i]] {
71+
return false
7372
}
7473
}
75-
return
74+
return true
7675
}

utils/strings_test.go

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,25 @@ func Test_ToUpper(t *testing.T) {
1515
AssertEqual(t, "/MY/NAME/IS/:PARAM/*", res)
1616
}
1717

18+
const (
19+
largeStr = "/RePos/GoFiBer/FibEr/iSsues/187643/CoMmEnts/RePos/GoFiBer/FibEr/iSsues/CoMmEnts"
20+
upperStr = "/REPOS/GOFIBER/FIBER/ISSUES/187643/COMMENTS/REPOS/GOFIBER/FIBER/ISSUES/COMMENTS"
21+
lowerStr = "/repos/gofiber/fiber/issues/187643/comments/repos/gofiber/fiber/issues/comments"
22+
)
23+
1824
func Benchmark_ToUpper(b *testing.B) {
19-
path := "/RePos/GoFiBer/FibEr/iSsues/187643/CoMmEnts"
2025
var res string
21-
2226
b.Run("fiber", func(b *testing.B) {
2327
for n := 0; n < b.N; n++ {
24-
res = ToUpper(path)
28+
res = ToUpper(largeStr)
2529
}
26-
AssertEqual(b, "/REPOS/GOFIBER/FIBER/ISSUES/187643/COMMENTS", res)
30+
AssertEqual(b, upperStr, res)
2731
})
2832
b.Run("default", func(b *testing.B) {
2933
for n := 0; n < b.N; n++ {
30-
res = strings.ToUpper(path)
34+
res = strings.ToUpper(largeStr)
3135
}
32-
AssertEqual(b, "/REPOS/GOFIBER/FIBER/ISSUES/187643/COMMENTS", res)
36+
AssertEqual(b, upperStr, res)
3337
})
3438
}
3539

@@ -48,19 +52,18 @@ func Test_ToLower(t *testing.T) {
4852
}
4953

5054
func Benchmark_ToLower(b *testing.B) {
51-
path := "/RePos/GoFiBer/FibEr/iSsues/187643/CoMmEnts"
5255
var res string
5356
b.Run("fiber", func(b *testing.B) {
5457
for n := 0; n < b.N; n++ {
55-
res = ToLower(path)
58+
res = ToLower(largeStr)
5659
}
57-
AssertEqual(b, "/repos/gofiber/fiber/issues/187643/comments", res)
60+
AssertEqual(b, lowerStr, res)
5861
})
5962
b.Run("default", func(b *testing.B) {
6063
for n := 0; n < b.N; n++ {
61-
res = strings.ToLower(path)
64+
res = strings.ToLower(largeStr)
6265
}
63-
AssertEqual(b, "/repos/gofiber/fiber/issues/187643/comments", res)
66+
AssertEqual(b, lowerStr, res)
6467
})
6568
}
6669

@@ -180,19 +183,16 @@ func Benchmark_Trim(b *testing.B) {
180183

181184
// go test -v -run=^$ -bench=Benchmark_EqualFold -benchmem -count=4
182185
func Benchmark_EqualFold(b *testing.B) {
183-
left := "/RePos/GoFiBer/FibEr/iSsues/187643/CoMmEnts"
184-
right := "/RePos/goFiber/Fiber/issues/187643/COMMENTS"
185186
var res bool
186-
187187
b.Run("fiber", func(b *testing.B) {
188188
for n := 0; n < b.N; n++ {
189-
res = EqualFold(left, right)
189+
res = EqualFold(upperStr, lowerStr)
190190
}
191191
AssertEqual(b, true, res)
192192
})
193193
b.Run("default", func(b *testing.B) {
194194
for n := 0; n < b.N; n++ {
195-
res = strings.EqualFold(left, right)
195+
res = strings.EqualFold(upperStr, lowerStr)
196196
}
197197
AssertEqual(b, true, res)
198198
})
@@ -208,6 +208,8 @@ func Test_EqualFold(t *testing.T) {
208208
AssertEqual(t, false, res)
209209
res = EqualFold("/dddddd", "eeeeee")
210210
AssertEqual(t, false, res)
211+
res = EqualFold("\na", "*A")
212+
AssertEqual(t, false, res)
211213
res = EqualFold("/MY3/NAME/IS/:PARAM/*", "/my3/name/is/:param/*")
212214
AssertEqual(t, true, res)
213215
res = EqualFold("/MY4/NAME/IS/:PARAM/*", "/my4/nAME/IS/:param/*")

0 commit comments

Comments
 (0)