xor.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package stun
  5. import (
  6. "runtime"
  7. "unsafe"
  8. )
  9. // #nosec
  10. const wordSize = int(unsafe.Sizeof(uintptr(0)))
  11. var supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64"
  12. // fastXORBytes xors in bulk. It only works on architectures that
  13. // support unaligned read/writes.
  14. //
  15. // #nosec
  16. func fastXORBytes(dst, a, b []byte) int {
  17. n := len(a)
  18. if len(b) < n {
  19. n = len(b)
  20. }
  21. w := n / wordSize
  22. if w > 0 {
  23. dw := *(*[]uintptr)(unsafe.Pointer(&dst))
  24. aw := *(*[]uintptr)(unsafe.Pointer(&a))
  25. bw := *(*[]uintptr)(unsafe.Pointer(&b))
  26. for i := 0; i < w; i++ {
  27. dw[i] = aw[i] ^ bw[i]
  28. }
  29. }
  30. for i := n - n%wordSize; i < n; i++ {
  31. dst[i] = a[i] ^ b[i]
  32. }
  33. return n
  34. }
  35. func safeXORBytes(dst, a, b []byte) int {
  36. n := len(a)
  37. if len(b) < n {
  38. n = len(b)
  39. }
  40. for i := 0; i < n; i++ {
  41. dst[i] = a[i] ^ b[i]
  42. }
  43. return n
  44. }
  45. // xorBytes xors the bytes in a and b. The destination is assumed to have enough
  46. // space. Returns the number of bytes xor'd.
  47. func xorBytes(dst, a, b []byte) int {
  48. if supportsUnaligned {
  49. return fastXORBytes(dst, a, b)
  50. }
  51. return safeXORBytes(dst, a, b)
  52. }