4
4
5
5
package mime
6
6
7
- import (
8
- "strings"
9
- )
10
-
11
- // isTSpecial reports whether rune is in 'tspecials' as defined by RFC
7
+ // isTSpecial reports whether c is in 'tspecials' as defined by RFC
12
8
// 1521 and RFC 2045.
13
- func isTSpecial (r rune ) bool {
14
- return strings .ContainsRune (`()<>@,;:\"/[]?=` , r )
9
+ func isTSpecial (c byte ) bool {
10
+ // tspecials := "(" / ")" / "<" / ">" / "@" /
11
+ // "," / ";" / ":" / "\" / <">
12
+ // "/" / "[" / "]" / "?" / "="
13
+ //
14
+ // mask is a 128-bit bitmap with 1s for allowed bytes,
15
+ // so that the byte c can be tested with a shift and an and.
16
+ // If c >= 128, then 1<<c and 1<<(c-64) will both be zero,
17
+ // and this function will return false.
18
+ const mask = 0 |
19
+ 1 << '(' |
20
+ 1 << ')' |
21
+ 1 << '<' |
22
+ 1 << '>' |
23
+ 1 << '@' |
24
+ 1 << ',' |
25
+ 1 << ';' |
26
+ 1 << ':' |
27
+ 1 << '\\' |
28
+ 1 << '"' |
29
+ 1 << '/' |
30
+ 1 << '[' |
31
+ 1 << ']' |
32
+ 1 << '?' |
33
+ 1 << '='
34
+ return ((uint64 (1 )<< c )& (mask & (1 << 64 - 1 )) |
35
+ (uint64 (1 )<< (c - 64 ))& (mask >> 64 )) != 0
15
36
}
16
37
17
- // isTokenChar reports whether rune is in 'token' as defined by RFC
38
+ // isTokenChar reports whether c is in 'token' as defined by RFC
18
39
// 1521 and RFC 2045.
19
- func isTokenChar (r rune ) bool {
40
+ func isTokenChar (c byte ) bool {
20
41
// token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
21
42
// or tspecials>
22
- return r > 0x20 && r < 0x7f && ! isTSpecial (r )
43
+ //
44
+ // mask is a 128-bit bitmap with 1s for allowed bytes,
45
+ // so that the byte c can be tested with a shift and an and.
46
+ // If c >= 128, then 1<<c and 1<<(c-64) will both be zero,
47
+ // and this function will return false.
48
+ const mask = 0 |
49
+ (1 << (10 )- 1 )<< '0' |
50
+ (1 << (26 )- 1 )<< 'a' |
51
+ (1 << (26 )- 1 )<< 'A' |
52
+ 1 << '!' |
53
+ 1 << '#' |
54
+ 1 << '$' |
55
+ 1 << '%' |
56
+ 1 << '&' |
57
+ 1 << '\'' |
58
+ 1 << '*' |
59
+ 1 << '+' |
60
+ 1 << '-' |
61
+ 1 << '.' |
62
+ 1 << '^' |
63
+ 1 << '_' |
64
+ 1 << '`' |
65
+ 1 << '|' |
66
+ 1 << '~'
67
+ return ((uint64 (1 )<< c )& (mask & (1 << 64 - 1 )) |
68
+ (uint64 (1 )<< (c - 64 ))& (mask >> 64 )) != 0
23
69
}
24
70
25
71
// isToken reports whether s is a 'token' as defined by RFC 1521
@@ -28,5 +74,10 @@ func isToken(s string) bool {
28
74
if s == "" {
29
75
return false
30
76
}
31
- return strings .IndexFunc (s , isNotTokenChar ) < 0
77
+ for _ , c := range []byte (s ) {
78
+ if ! isTokenChar (c ) {
79
+ return false
80
+ }
81
+ }
82
+ return true
32
83
}
0 commit comments