fckeuspy-go/vendor/github.com/makiuchi-d/gozxing/bit_array.go
2025-09-28 21:03:39 +02:00

256 lines
5.1 KiB
Go

package gozxing
import (
"math/bits"
errors "golang.org/x/xerrors"
)
type BitArray struct {
bits []uint32
size int
}
func NewEmptyBitArray() *BitArray {
return &BitArray{makeArray(1), 0}
}
func NewBitArray(size int) *BitArray {
return &BitArray{makeArray(size), size}
}
func (b *BitArray) GetSize() int {
return b.size
}
func (b *BitArray) GetSizeInBytes() int {
return (b.size + 7) / 8
}
func (b *BitArray) ensureCapacity(size int) {
if size > len(b.bits)*32 {
newBits := makeArray(size)
copy(newBits, b.bits)
b.bits = newBits
}
}
func (b *BitArray) Get(i int) bool {
return (b.bits[i/32] & (1 << uint(i%32))) != 0
}
func (b *BitArray) Set(i int) {
b.bits[i/32] |= 1 << uint(i%32)
}
func (b *BitArray) Flip(i int) {
b.bits[i/32] ^= 1 << uint(i%32)
}
func (b *BitArray) GetNextSet(from int) int {
if from >= b.size {
return b.size
}
bitsOffset := from / 32
currentBits := b.bits[bitsOffset]
currentBits &= -(1 << uint(from&0x1F))
for currentBits == 0 {
bitsOffset++
if bitsOffset == len(b.bits) {
return b.size
}
currentBits = b.bits[bitsOffset]
}
result := (bitsOffset * 32) + bits.TrailingZeros32(currentBits)
if result > b.size {
return b.size
}
return result
}
func (b *BitArray) GetNextUnset(from int) int {
if from >= b.size {
return b.size
}
bitsOffset := from / 32
currentBits := ^b.bits[bitsOffset]
currentBits &= -(1 << uint(from&0x1F))
for currentBits == 0 {
bitsOffset++
if bitsOffset == len(b.bits) {
return b.size
}
currentBits = ^b.bits[bitsOffset]
}
result := (bitsOffset * 32) + bits.TrailingZeros32(currentBits)
if result > b.size {
return b.size
}
return result
}
func (b *BitArray) SetBulk(i int, newBits uint32) {
b.bits[i/32] = newBits
}
func (b *BitArray) SetRange(start, end int) error {
if end < start || start < 0 || end > b.size {
return errors.New("IllegalArgumentException")
}
if end == start {
return nil
}
end--
firstInt := start / 32
lastInt := end / 32
for i := firstInt; i <= lastInt; i++ {
firstBit := 0
lastBit := 31
if i == firstInt {
firstBit = start % 32
}
if i == lastInt {
lastBit = end % 32
}
mask := (2 << uint(lastBit)) - (1 << uint(firstBit))
b.bits[i] |= uint32(mask)
}
return nil
}
func (b *BitArray) Clear() {
for i := range b.bits {
b.bits[i] = 0
}
}
func (b *BitArray) IsRange(start, end int, value bool) (bool, error) {
if end < start || start < 0 || end > b.size {
return false, errors.New("IllegalArgumentException")
}
if end == start {
return true, nil
}
end--
firstInt := start / 32
lastInt := end / 32
for i := firstInt; i <= lastInt; i++ {
firstBit := 0
lastBit := 31
if i == firstInt {
firstBit = start % 32
}
if i == lastInt {
lastBit = end % 32
}
mask := uint32((2 << uint(lastBit)) - (1 << uint(firstBit)))
expect := uint32(0)
if value {
expect = mask
}
if (b.bits[i] & mask) != expect {
return false, nil
}
}
return true, nil
}
func (b *BitArray) AppendBit(bit bool) {
b.ensureCapacity(b.size + 1)
if bit {
b.bits[b.size/32] |= 1 << uint(b.size%32)
}
b.size++
}
func (b *BitArray) AppendBits(value int, numBits int) error {
if numBits < 0 || numBits > 32 {
return errors.New("IllegalArgumentException: Num bits must be between 0 and 32")
}
b.ensureCapacity(b.size + numBits)
for numBitsLeft := numBits; numBitsLeft > 0; numBitsLeft-- {
b.AppendBit(((value >> uint(numBitsLeft-1)) & 0x01) == 1)
}
return nil
}
func (b *BitArray) AppendBitArray(other *BitArray) {
otherSize := other.size
b.ensureCapacity(b.size + otherSize)
for i := 0; i < otherSize; i++ {
b.AppendBit(other.Get(i))
}
}
func (b *BitArray) Xor(other *BitArray) error {
if b.size != other.size {
return errors.New("IllegalArgumentException: Sizes don't match")
}
for i := 0; i < len(b.bits); i++ {
b.bits[i] ^= other.bits[i]
}
return nil
}
func (b *BitArray) ToBytes(bitOffset int, array []byte, offset, numBytes int) {
for i := 0; i < numBytes; i++ {
theByte := byte(0)
for j := 0; j < 8; j++ {
if b.Get(bitOffset) {
theByte |= 1 << uint(7-j)
}
bitOffset++
}
array[offset+i] = theByte
}
}
func (b *BitArray) GetBitArray() []uint32 {
return b.bits
}
func (b *BitArray) Reverse() {
newBits := make([]uint32, len(b.bits))
len := (b.size - 1) / 32
oldBitsLen := len + 1
for i := 0; i < oldBitsLen; i++ {
newBits[len-i] = bits.Reverse32(b.bits[i])
}
if b.size != oldBitsLen*32 {
leftOffset := uint(oldBitsLen*32 - b.size)
currentInt := newBits[0] >> leftOffset
for i := 1; i < oldBitsLen; i++ {
nextInt := newBits[i]
currentInt |= nextInt << uint(32-leftOffset)
newBits[i-1] = currentInt
currentInt = nextInt >> leftOffset
}
newBits[oldBitsLen-1] = currentInt
}
b.bits = newBits
}
func makeArray(size int) []uint32 {
return make([]uint32, (size+31)/32)
}
// equals()
// hasCode()
func (b *BitArray) String() string {
result := make([]byte, 0, b.size+(b.size/8)+1)
for i := 0; i < b.size; i++ {
if (i % 8) == 0 {
result = append(result, ' ')
}
if b.Get(i) {
result = append(result, 'X')
} else {
result = append(result, '.')
}
}
return string(result)
}
// clone()