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