1
2
3
4
5
6
7
8 package cipher
9
10 import (
11 "runtime"
12 "unsafe"
13 )
14
15
16
17 func xorBytes(dst, a, b []byte) int {
18 n := len(a)
19 if len(b) < n {
20 n = len(b)
21 }
22 if n == 0 {
23 return 0
24 }
25
26 switch {
27 case supportsUnaligned:
28 fastXORBytes(dst, a, b, n)
29 default:
30
31
32
33
34
35 safeXORBytes(dst, a, b, n)
36 }
37 return n
38 }
39
40 const wordSize = int(unsafe.Sizeof(uintptr(0)))
41 const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x"
42
43
44
45
46 func fastXORBytes(dst, a, b []byte, n int) {
47
48 _ = dst[n-1]
49
50 w := n / wordSize
51 if w > 0 {
52 dw := *(*[]uintptr)(unsafe.Pointer(&dst))
53 aw := *(*[]uintptr)(unsafe.Pointer(&a))
54 bw := *(*[]uintptr)(unsafe.Pointer(&b))
55 for i := 0; i < w; i++ {
56 dw[i] = aw[i] ^ bw[i]
57 }
58 }
59
60 for i := (n - n%wordSize); i < n; i++ {
61 dst[i] = a[i] ^ b[i]
62 }
63 }
64
65
66 func safeXORBytes(dst, a, b []byte, n int) {
67 for i := 0; i < n; i++ {
68 dst[i] = a[i] ^ b[i]
69 }
70 }
71
72
73
74 func fastXORWords(dst, a, b []byte) {
75 dw := *(*[]uintptr)(unsafe.Pointer(&dst))
76 aw := *(*[]uintptr)(unsafe.Pointer(&a))
77 bw := *(*[]uintptr)(unsafe.Pointer(&b))
78 n := len(b) / wordSize
79 for i := 0; i < n; i++ {
80 dw[i] = aw[i] ^ bw[i]
81 }
82 }
83
84
85
86 func xorWords(dst, a, b []byte) {
87 if supportsUnaligned {
88 fastXORWords(dst, a, b)
89 } else {
90 safeXORBytes(dst, a, b, len(b))
91 }
92 }
93
View as plain text