Skip to content

Commit dacf4b1

Browse files
author
Achille
authored
use segmentio/asm (#93)
1 parent 95064a2 commit dacf4b1

19 files changed

Lines changed: 38 additions & 839 deletions

ascii/ascii.go

Lines changed: 0 additions & 75 deletions
This file was deleted.

ascii/ascii_default.go

Lines changed: 0 additions & 18 deletions
This file was deleted.

ascii/equal_fold.go

Lines changed: 11 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
11
//go:generate go run equal_fold_asm.go -out equal_fold_amd64.s -stubs equal_fold_amd64.go
22
package ascii
33

4-
import "unsafe"
4+
import (
5+
"github.com/segmentio/asm/ascii"
6+
)
57

68
// EqualFold is a version of bytes.EqualFold designed to work on ASCII input
79
// instead of UTF-8.
810
//
911
// When the program has guarantees that the input is composed of ASCII
1012
// characters only, it allows for greater optimizations.
1113
func EqualFold(a, b []byte) bool {
12-
return EqualFoldString(unsafeString(a), unsafeString(b))
14+
return ascii.EqualFold(a, b)
1315
}
1416

1517
func HasPrefixFold(s, prefix []byte) bool {
16-
return len(s) >= len(prefix) && EqualFold(s, prefix)
18+
return ascii.HasPrefixFold(s, prefix)
1719
}
1820

19-
func HasSuffixFold(s, prefix []byte) bool {
20-
return len(s) >= len(prefix) && EqualFold(s[len(s)-len(prefix):], prefix)
21+
func HasSuffixFold(s, suffix []byte) bool {
22+
return ascii.HasSuffixFold(s, suffix)
2123
}
2224

2325
// EqualFoldString is a version of strings.EqualFold designed to work on ASCII
@@ -26,81 +28,13 @@ func HasSuffixFold(s, prefix []byte) bool {
2628
// When the program has guarantees that the input is composed of ASCII
2729
// characters only, it allows for greater optimizations.
2830
func EqualFoldString(a, b string) bool {
29-
if len(a) != len(b) {
30-
return false
31-
}
32-
33-
n := uintptr(len(a))
34-
p := *(*unsafe.Pointer)(unsafe.Pointer(&a))
35-
q := *(*unsafe.Pointer)(unsafe.Pointer(&b))
36-
c := byte(0)
37-
38-
// Pre-check to avoid the other tests that would all evaluate to false.
39-
// For very small strings, this helps reduce the processing overhead.
40-
if n >= 8 {
41-
// If there is more than 32 bytes to copy, use the AVX optimized version,
42-
// otherwise the overhead of the function call tends to be greater than
43-
// looping 2 or 3 times over 8 bytes.
44-
if n >= 32 && asm.equalFoldAVX2 != nil {
45-
if asm.equalFoldAVX2((*byte)(p), (*byte)(q), n) == 0 {
46-
return false
47-
}
48-
k := (n / 16) * 16
49-
p = unsafe.Pointer(uintptr(p) + k)
50-
q = unsafe.Pointer(uintptr(q) + k)
51-
n -= k
52-
}
53-
for n >= 8 {
54-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 0))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 0))]
55-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 1))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 1))]
56-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 2))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 2))]
57-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 3))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 3))]
58-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 4))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 4))]
59-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 5))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 5))]
60-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 6))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 6))]
61-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 7))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 7))]
62-
63-
if c != 0 {
64-
return false
65-
}
66-
67-
p = unsafe.Pointer(uintptr(p) + 8)
68-
q = unsafe.Pointer(uintptr(q) + 8)
69-
n -= 8
70-
}
71-
}
72-
73-
switch n {
74-
case 7:
75-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 6))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 6))]
76-
fallthrough
77-
case 6:
78-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 5))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 5))]
79-
fallthrough
80-
case 5:
81-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 4))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 4))]
82-
fallthrough
83-
case 4:
84-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 3))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 3))]
85-
fallthrough
86-
case 3:
87-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 2))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 2))]
88-
fallthrough
89-
case 2:
90-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 1))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 1))]
91-
fallthrough
92-
case 1:
93-
c |= lower[*(*uint8)(unsafe.Pointer(uintptr(p) + 0))] ^ lower[*(*uint8)(unsafe.Pointer(uintptr(q) + 0))]
94-
}
95-
96-
return c == 0
97-
31+
return ascii.EqualFoldString(a, b)
9832
}
9933

10034
func HasPrefixFoldString(s, prefix string) bool {
101-
return len(s) >= len(prefix) && EqualFoldString(s[:len(prefix)], prefix)
35+
return ascii.HasPrefixFoldString(s, prefix)
10236
}
10337

104-
func HasSuffixFoldString(s, prefix string) bool {
105-
return len(s) >= len(prefix) && EqualFoldString(s[len(s)-len(prefix):], prefix)
38+
func HasSuffixFoldString(s, suffix string) bool {
39+
return ascii.HasSuffixFoldString(s, suffix)
10640
}

ascii/equal_fold_amd64.go

Lines changed: 0 additions & 6 deletions
This file was deleted.

ascii/equal_fold_amd64.s

Lines changed: 0 additions & 103 deletions
This file was deleted.

0 commit comments

Comments
 (0)