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 }