git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/barcode/utils/bitlist.go (about)

     1  package utils
     2  
     3  // BitList is a list that contains bits
     4  type BitList struct {
     5  	count int
     6  	data  []int32
     7  }
     8  
     9  // NewBitList returns a new BitList with the given length
    10  // all bits are initialize with false
    11  func NewBitList(capacity int) *BitList {
    12  	bl := new(BitList)
    13  	bl.count = capacity
    14  	x := 0
    15  	if capacity%32 != 0 {
    16  		x = 1
    17  	}
    18  	bl.data = make([]int32, capacity/32+x)
    19  	return bl
    20  }
    21  
    22  // Len returns the number of contained bits
    23  func (bl *BitList) Len() int {
    24  	return bl.count
    25  }
    26  
    27  func (bl *BitList) grow() {
    28  	growBy := len(bl.data)
    29  	if growBy < 128 {
    30  		growBy = 128
    31  	} else if growBy >= 1024 {
    32  		growBy = 1024
    33  	}
    34  
    35  	nd := make([]int32, len(bl.data)+growBy)
    36  	copy(nd, bl.data)
    37  	bl.data = nd
    38  }
    39  
    40  // AddBit appends the given bits to the end of the list
    41  func (bl *BitList) AddBit(bits ...bool) {
    42  	for _, bit := range bits {
    43  		itmIndex := bl.count / 32
    44  		for itmIndex >= len(bl.data) {
    45  			bl.grow()
    46  		}
    47  		bl.SetBit(bl.count, bit)
    48  		bl.count++
    49  	}
    50  }
    51  
    52  // SetBit sets the bit at the given index to the given value
    53  func (bl *BitList) SetBit(index int, value bool) {
    54  	itmIndex := index / 32
    55  	itmBitShift := 31 - (index % 32)
    56  	if value {
    57  		bl.data[itmIndex] = bl.data[itmIndex] | 1<<uint(itmBitShift)
    58  	} else {
    59  		bl.data[itmIndex] = bl.data[itmIndex] & ^(1 << uint(itmBitShift))
    60  	}
    61  }
    62  
    63  // GetBit returns the bit at the given index
    64  func (bl *BitList) GetBit(index int) bool {
    65  	itmIndex := index / 32
    66  	itmBitShift := 31 - (index % 32)
    67  	return ((bl.data[itmIndex] >> uint(itmBitShift)) & 1) == 1
    68  }
    69  
    70  // AddByte appends all 8 bits of the given byte to the end of the list
    71  func (bl *BitList) AddByte(b byte) {
    72  	for i := 7; i >= 0; i-- {
    73  		bl.AddBit(((b >> uint(i)) & 1) == 1)
    74  	}
    75  }
    76  
    77  // AddBits appends the last (LSB) 'count' bits of 'b' the the end of the list
    78  func (bl *BitList) AddBits(b int, count byte) {
    79  	for i := int(count) - 1; i >= 0; i-- {
    80  		bl.AddBit(((b >> uint(i)) & 1) == 1)
    81  	}
    82  }
    83  
    84  // GetBytes returns all bits of the BitList as a []byte
    85  func (bl *BitList) GetBytes() []byte {
    86  	len := bl.count >> 3
    87  	if (bl.count % 8) != 0 {
    88  		len++
    89  	}
    90  	result := make([]byte, len)
    91  	for i := 0; i < len; i++ {
    92  		shift := (3 - (i % 4)) * 8
    93  		result[i] = (byte)((bl.data[i/4] >> uint(shift)) & 0xFF)
    94  	}
    95  	return result
    96  }
    97  
    98  // IterateBytes iterates through all bytes contained in the BitList
    99  func (bl *BitList) IterateBytes() <-chan byte {
   100  	res := make(chan byte)
   101  
   102  	go func() {
   103  		c := bl.count
   104  		shift := 24
   105  		i := 0
   106  		for c > 0 {
   107  			res <- byte((bl.data[i] >> uint(shift)) & 0xFF)
   108  			shift -= 8
   109  			if shift < 0 {
   110  				shift = 24
   111  				i++
   112  			}
   113  			c -= 8
   114  		}
   115  		close(res)
   116  	}()
   117  
   118  	return res
   119  }