github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/longbits/bit_array.go (about)

     1  // Copyright 2020 Insolar Network Ltd.
     2  // All rights reserved.
     3  // This material is licensed under the Insolar License version 1.0,
     4  // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md.
     5  
     6  package longbits
     7  
     8  import (
     9  	"math/bits"
    10  
    11  	"github.com/insolar/vanilla/throw"
    12  )
    13  
    14  type IndexedBits interface {
    15  	BitBool(index int) bool
    16  	BitValue(index int) byte
    17  	Byte(index int) byte
    18  	BitLen() int
    19  	SearchBit(startAt int, bit bool) int
    20  }
    21  
    22  func BitPos(index int) (bytePos int, bitPos uint8) {
    23  	if index < 0 {
    24  		panic(throw.IllegalValue())
    25  	}
    26  	return index >> 3, uint8(index & 0x07)
    27  }
    28  
    29  type BitSlice = BitSliceLSB
    30  type BitSliceLSB []byte
    31  
    32  func (v BitSliceLSB) BitMasked(index int) (value byte, mask uint8) {
    33  	bytePos, bitPos := BitPos(index)
    34  	mask = 1 << bitPos
    35  	return v[bytePos] & mask, mask
    36  }
    37  
    38  func (v BitSliceLSB) BitBool(index int) bool {
    39  	if b, _ := v.BitMasked(index); b != 0 {
    40  		return true
    41  	}
    42  	return false
    43  }
    44  
    45  func (v BitSliceLSB) BitValue(index int) byte {
    46  	if b, _ := v.BitMasked(index); b != 0 {
    47  		return 1
    48  	}
    49  	return 0
    50  }
    51  
    52  func (v BitSliceLSB) Byte(index int) byte {
    53  	return v[index]
    54  }
    55  
    56  func (v BitSliceLSB) BitLen() int {
    57  	return len(v) << 3
    58  }
    59  
    60  func (v BitSliceLSB) SearchBit(startAt int, bit bool) int {
    61  	byteIndex, bitIndex := BitPos(startAt)
    62  	if byteIndex >= len(v) {
    63  		return -1
    64  	}
    65  
    66  	if bit {
    67  		return v.searchBit1(byteIndex, bitIndex)
    68  	}
    69  	return v.searchBit0(byteIndex, bitIndex)
    70  }
    71  
    72  func (v BitSliceLSB) searchBit1(bytePos int, bitPos byte) int {
    73  	b := v[bytePos] >> bitPos
    74  	if b != 0 {
    75  		return bytePos<<3 + int(bitPos) + bits.TrailingZeros8(b)
    76  	}
    77  
    78  	for bytePos++; bytePos < len(v); bytePos++ {
    79  		b := v[bytePos]
    80  		if b != 0 {
    81  			return bytePos<<3 + bits.TrailingZeros8(b)
    82  		}
    83  	}
    84  	return -1
    85  }
    86  
    87  func (v BitSliceLSB) searchBit0(bytePos int, bitPos byte) int {
    88  	b := (^v[bytePos]) >> bitPos
    89  	if b != 0 {
    90  		return bytePos<<3 + int(bitPos) + bits.TrailingZeros8(b)
    91  	}
    92  
    93  	for bytePos++; bytePos < len(v); bytePos++ {
    94  		b := v[bytePos]
    95  		if b != 0xFF {
    96  			return bytePos<<3 + bits.TrailingZeros8(^b)
    97  		}
    98  	}
    99  	return -1
   100  }
   101  
   102  /*********************************************************/
   103  
   104  type BitSliceMSB []byte
   105  
   106  func (v BitSliceMSB) BitMasked(index int) (value byte, mask uint8) {
   107  	bytePos, bitPos := BitPos(index)
   108  	mask = 0x80 >> bitPos
   109  	return v[bytePos] & mask, mask
   110  }
   111  
   112  func (v BitSliceMSB) BitBool(index int) bool {
   113  	if b, _ := v.BitMasked(index); b != 0 {
   114  		return true
   115  	}
   116  	return false
   117  }
   118  
   119  func (v BitSliceMSB) BitValue(index int) byte {
   120  	if b, _ := v.BitMasked(index); b != 0 {
   121  		return 1
   122  	}
   123  	return 0
   124  }
   125  
   126  func (v BitSliceMSB) Byte(index int) byte {
   127  	return v[index]
   128  }
   129  
   130  func (v BitSliceMSB) BitLen() int {
   131  	return len(v) << 3
   132  }
   133  
   134  func (v BitSliceMSB) SearchBit(startAt int, bit bool) int {
   135  	byteIndex, bitIndex := BitPos(startAt)
   136  	if byteIndex >= len(v) {
   137  		return -1
   138  	}
   139  
   140  	if bit {
   141  		return v.searchBit1(byteIndex, bitIndex)
   142  	}
   143  	return v.searchBit0(byteIndex, bitIndex)
   144  }
   145  
   146  func (v BitSliceMSB) searchBit1(bytePos int, bitPos byte) int {
   147  	b := v[bytePos] << bitPos
   148  	if b != 0 {
   149  		return bytePos<<3 + int(bitPos) + bits.LeadingZeros8(b)
   150  	}
   151  
   152  	for bytePos++; bytePos < len(v); bytePos++ {
   153  		b := v[bytePos]
   154  		if b != 0 {
   155  			return bytePos<<3 + bits.LeadingZeros8(b)
   156  		}
   157  	}
   158  	return -1
   159  }
   160  
   161  func (v BitSliceMSB) searchBit0(bytePos int, bitPos byte) int {
   162  	b := (^v[bytePos]) << bitPos
   163  	if b != 0 {
   164  		return bytePos<<3 + int(bitPos) + bits.LeadingZeros8(b)
   165  	}
   166  
   167  	for bytePos++; bytePos < len(v); bytePos++ {
   168  		b := v[bytePos]
   169  		if b != 0xFF {
   170  			return bytePos<<3 + bits.LeadingZeros8(^b)
   171  		}
   172  	}
   173  	return -1
   174  }