@@ -21,38 +21,99 @@ package util
21
21
// current capacity. The bit index starts at 0.
22
22
type FilterBitArray []byte
23
23
24
+ const (
25
+ byteMask byte = 0xFF
26
+ byteSize = 8
27
+ )
28
+
24
29
// NewFilterBitArray creates an array with the specified bit-size. This is an
25
30
// optimization to make array once for the expected capacity rather than
26
31
// using Set function to auto-increase the array.
27
32
func NewFilterBitArray (size uint ) FilterBitArray {
28
- ba := make (FilterBitArray , (size - 1 )/ 8 + 1 )
33
+ ba := make (FilterBitArray , (size - 1 )/ byteSize + 1 )
29
34
return ba
30
35
}
31
36
37
+ // NewFilterBitArrayFromBytes reconstructs an array from given byte array.
38
+ func NewFilterBitArrayFromBytes (bytes []byte ) FilterBitArray {
39
+ bitArray := FilterBitArray {}
40
+ bitArray .FromBytes (bytes )
41
+ return bitArray
42
+ }
43
+
32
44
// Capacity returns the number of bits in the FilterBitArray.
33
45
func (ba * FilterBitArray ) Capacity () uint {
34
- return uint (len (* ba ) * 8 )
46
+ return uint (len (* ba ) * byteSize )
35
47
}
36
48
37
49
// Set assigns 1 to the specified bit-index, which is starting from 0.
38
50
// Set automatically increases the array to accommodate the bit-index.
39
51
func (ba * FilterBitArray ) Set (i uint ) {
40
- // Location of i in the array index is floor(i/8 ) + 1. If it exceeds the
52
+ // Location of i in the array index is floor(i/byte_size ) + 1. If it exceeds the
41
53
// current byte array, we'll make a new one large enough to include the
42
54
// specified bit-index
43
55
if i >= ba .Capacity () {
44
- array := make ([]byte , i / 8 + 1 )
45
- copy (array , * ba )
46
- * ba = array
56
+ ba .expand (i / byteSize + 1 )
57
+ }
58
+ (* ba )[i / byteSize ] |= 1 << (i % byteSize )
59
+ }
60
+
61
+ // SetRange assigns 1 to the bit-indexes specified by range [begin, end]
62
+ // Set automatically increases the array to accommodate the bit-index.
63
+ func (ba * FilterBitArray ) SetRange (begin uint , end uint ) {
64
+ // Location of i in the array index is floor(i/byte_size) + 1. If it exceeds the
65
+ // current byte array, we'll make a new one large enough to include the
66
+ // specified bit-index
67
+ startByteIndex := ba .byteIndex (begin )
68
+ endByteIndex := ba .byteIndex (end )
69
+
70
+ if end >= ba .Capacity () {
71
+ ba .expand (endByteIndex + 1 )
72
+ }
73
+
74
+ firstByteMask := byteMask << (begin % byteSize )
75
+ lastByteMask := byteMask >> ((byteSize - end - 1 ) % byteSize )
76
+
77
+ if startByteIndex == endByteIndex {
78
+ (* ba )[startByteIndex ] |= (firstByteMask & lastByteMask )
79
+ } else {
80
+ (* ba )[startByteIndex ] |= firstByteMask
81
+ for i := startByteIndex + 1 ; i < endByteIndex ; i ++ {
82
+ (* ba )[i ] = byteMask
83
+ }
84
+ (* ba )[endByteIndex ] |= lastByteMask
47
85
}
48
- (* ba )[i / 8 ] |= 1 << (i % 8 )
49
86
}
50
87
51
88
// Unset assigns 0 the specified bit-index. If bit-index is larger than capacity,
52
89
// do nothing.
53
90
func (ba * FilterBitArray ) Unset (i uint ) {
54
91
if i < ba .Capacity () {
55
- (* ba )[i / 8 ] &^= 1 << (i % 8 )
92
+ (* ba )[i / byteSize ] &^= 1 << (i % byteSize )
93
+ }
94
+ }
95
+
96
+ // UnsetRange assigns 0 to all bits in range [begin, end]. If bit-index is larger than capacity,
97
+ // do nothing.
98
+ func (ba * FilterBitArray ) UnsetRange (begin uint , end uint ) {
99
+ if begin > ba .Capacity () || begin == end {
100
+ return
101
+ }
102
+
103
+ startByteIndex := ba .byteIndex (begin )
104
+ endByteIndex := ba .byteIndex (end )
105
+
106
+ firstByteMask := byteMask << (begin % byteSize )
107
+ lastByteMask := byteMask >> ((byteSize - end - 1 ) % byteSize )
108
+
109
+ if startByteIndex == endByteIndex {
110
+ (* ba )[startByteIndex ] &= ^ (firstByteMask & lastByteMask )
111
+ } else {
112
+ (* ba )[startByteIndex ] &= ^ firstByteMask
113
+ for i := startByteIndex + 1 ; i < endByteIndex ; i ++ {
114
+ (* ba )[i ] = 0
115
+ }
116
+ (* ba )[endByteIndex ] &= ^ lastByteMask
56
117
}
57
118
}
58
119
@@ -61,7 +122,7 @@ func (ba *FilterBitArray) Unset(i uint) {
61
122
// a power of 2 if not 0.
62
123
func (ba * FilterBitArray ) ValueAt (i uint ) byte {
63
124
if i < ba .Capacity () {
64
- return (* ba )[i / 8 ] & (1 << (i % 8 ))
125
+ return (* ba )[i / byteSize ] & (1 << (i % byteSize ))
65
126
}
66
127
return 0
67
128
}
@@ -80,3 +141,13 @@ func (ba *FilterBitArray) ToBytes() []byte {
80
141
func (ba * FilterBitArray ) FromBytes (bytes []byte ) {
81
142
* ba = bytes
82
143
}
144
+
145
+ func (ba * FilterBitArray ) expand (newSize uint ) {
146
+ array := make ([]byte , newSize )
147
+ copy (array , * ba )
148
+ * ba = array
149
+ }
150
+
151
+ func (ba * FilterBitArray ) byteIndex (i uint ) uint {
152
+ return i / byteSize
153
+ }
0 commit comments