11//go:generate go run equal_fold_asm.go -out equal_fold_amd64.s -stubs equal_fold_amd64.go
22package 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.
1113func EqualFold (a , b []byte ) bool {
12- return EqualFoldString ( unsafeString ( a ), unsafeString ( b ) )
14+ return ascii . EqualFold ( a , b )
1315}
1416
1517func 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.
2830func 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
10034func 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}
0 commit comments