github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/utilities/common/bitutil/bitutil.go (about)

     1  package bitutil
     2  
     3  import (
     4  	"runtime"
     5  	"unsafe"
     6  )
     7  
     8  const wordSize = int(unsafe.Sizeof(uintptr(0)))
     9  const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x"
    10  
    11  func XORBytes(dst, a, b []byte) int {
    12  	if supportsUnaligned {
    13  		return fastXORBytes(dst, a, b)
    14  	}
    15  	return safeXORBytes(dst, a, b)
    16  }
    17  
    18  func fastXORBytes(dst, a, b []byte) int {
    19  	n := len(a)
    20  	if len(b) < n {
    21  		n = len(b)
    22  	}
    23  	w := n / wordSize
    24  	if w > 0 {
    25  		dw := *(*[]uintptr)(unsafe.Pointer(&dst))
    26  		aw := *(*[]uintptr)(unsafe.Pointer(&a))
    27  		bw := *(*[]uintptr)(unsafe.Pointer(&b))
    28  		for i := 0; i < w; i++ {
    29  			dw[i] = aw[i] ^ bw[i]
    30  		}
    31  	}
    32  	for i := n - n%wordSize; i < n; i++ {
    33  		dst[i] = a[i] ^ b[i]
    34  	}
    35  	return n
    36  }
    37  
    38  func safeXORBytes(dst, a, b []byte) int {
    39  	n := len(a)
    40  	if len(b) < n {
    41  		n = len(b)
    42  	}
    43  	for i := 0; i < n; i++ {
    44  		dst[i] = a[i] ^ b[i]
    45  	}
    46  	return n
    47  }
    48  
    49  func ANDBytes(dst, a, b []byte) int {
    50  	if supportsUnaligned {
    51  		return fastANDBytes(dst, a, b)
    52  	}
    53  	return safeANDBytes(dst, a, b)
    54  }
    55  
    56  func fastANDBytes(dst, a, b []byte) int {
    57  	n := len(a)
    58  	if len(b) < n {
    59  		n = len(b)
    60  	}
    61  	w := n / wordSize
    62  	if w > 0 {
    63  		dw := *(*[]uintptr)(unsafe.Pointer(&dst))
    64  		aw := *(*[]uintptr)(unsafe.Pointer(&a))
    65  		bw := *(*[]uintptr)(unsafe.Pointer(&b))
    66  		for i := 0; i < w; i++ {
    67  			dw[i] = aw[i] & bw[i]
    68  		}
    69  	}
    70  	for i := n - n%wordSize; i < n; i++ {
    71  		dst[i] = a[i] & b[i]
    72  	}
    73  	return n
    74  }
    75  
    76  func safeANDBytes(dst, a, b []byte) int {
    77  	n := len(a)
    78  	if len(b) < n {
    79  		n = len(b)
    80  	}
    81  	for i := 0; i < n; i++ {
    82  		dst[i] = a[i] & b[i]
    83  	}
    84  	return n
    85  }
    86  
    87  func ORBytes(dst, a, b []byte) int {
    88  	if supportsUnaligned {
    89  		return fastORBytes(dst, a, b)
    90  	}
    91  	return safeORBytes(dst, a, b)
    92  }
    93  
    94  func fastORBytes(dst, a, b []byte) int {
    95  	n := len(a)
    96  	if len(b) < n {
    97  		n = len(b)
    98  	}
    99  	w := n / wordSize
   100  	if w > 0 {
   101  		dw := *(*[]uintptr)(unsafe.Pointer(&dst))
   102  		aw := *(*[]uintptr)(unsafe.Pointer(&a))
   103  		bw := *(*[]uintptr)(unsafe.Pointer(&b))
   104  		for i := 0; i < w; i++ {
   105  			dw[i] = aw[i] | bw[i]
   106  		}
   107  	}
   108  	for i := n - n%wordSize; i < n; i++ {
   109  		dst[i] = a[i] | b[i]
   110  	}
   111  	return n
   112  }
   113  
   114  func safeORBytes(dst, a, b []byte) int {
   115  	n := len(a)
   116  	if len(b) < n {
   117  		n = len(b)
   118  	}
   119  	for i := 0; i < n; i++ {
   120  		dst[i] = a[i] | b[i]
   121  	}
   122  	return n
   123  }
   124  
   125  func TestBytes(p []byte) bool {
   126  	if supportsUnaligned {
   127  		return fastTestBytes(p)
   128  	}
   129  	return safeTestBytes(p)
   130  }
   131  
   132  func fastTestBytes(p []byte) bool {
   133  	n := len(p)
   134  	w := n / wordSize
   135  	if w > 0 {
   136  		pw := *(*[]uintptr)(unsafe.Pointer(&p))
   137  		for i := 0; i < w; i++ {
   138  			if pw[i] != 0 {
   139  				return true
   140  			}
   141  		}
   142  	}
   143  	for i := n - n%wordSize; i < n; i++ {
   144  		if p[i] != 0 {
   145  			return true
   146  		}
   147  	}
   148  	return false
   149  }
   150  
   151  func safeTestBytes(p []byte) bool {
   152  	for i := 0; i < len(p); i++ {
   153  		if p[i] != 0 {
   154  			return true
   155  		}
   156  	}
   157  	return false
   158  }