@@ -11,59 +11,66 @@ import (
1111
1212const (
1313 blockSize = 8
14+ MaxIndex = uint64 (1 << 34 )
1415)
1516
1617type Bitmap struct {
17- data []byte
18- size uint64
18+ bits []byte
19+
20+ blocks uint64
1921 max uint64
20- mux sync.RWMutex
2122 lockoff bool
23+
24+ mux sync.RWMutex
2225}
2326
2427type Option func (* Bitmap )
2528
26- func DisableLock () Option {
29+ func OptDisableLock () Option {
2730 return func (o * Bitmap ) {
2831 o .lockoff = true
2932 }
3033}
3134
32- func New (maxIndex uint64 , opts ... Option ) * Bitmap {
33- size := maxIndex / blockSize + maxIndex % blockSize
34-
35- bm := & Bitmap {
36- max : size * blockSize ,
37- size : size ,
38- data : make ([]byte , size ),
35+ func OptMaxIndex (index uint64 ) Option {
36+ return func (o * Bitmap ) {
37+ o .max = index
3938 }
39+ }
40+
41+ func New (opts ... Option ) * Bitmap {
42+ bm := & Bitmap {max : 1 }
4043
4144 for _ , opt := range opts {
4245 opt (bm )
4346 }
4447
48+ bm .resize (bm .max )
49+
4550 return bm
4651}
4752
48- func (b * Bitmap ) CopyTo (dst * Bitmap ) {
49- if ! b .lockoff {
50- b .mux .Lock ()
51- defer b .mux .Unlock ()
52- }
53- if ! dst .lockoff {
54- dst .mux .Lock ()
55- defer dst .mux .Unlock ()
53+ func (b * Bitmap ) resize (index uint64 ) {
54+ size := index / blockSize
55+ if index - (size % blockSize ) > 0 {
56+ size ++
5657 }
5758
58- dst .data = make ([]byte , len (b .data ))
59- copy (dst .data , b .data )
60- dst .size = b .size
61- dst .max = b .max
62- dst .lockoff = b .lockoff
59+ b .bits = append (b .bits , make ([]byte , size - b .blocks )... )
60+ b .blocks = uint64 (len (b .bits ))
61+ b .max = b .blocks * blockSize - 1
62+ }
63+
64+ func (b * Bitmap ) getBlock (index uint64 ) uint64 {
65+ return index / blockSize
66+ }
67+
68+ func (b * Bitmap ) getBit (index uint64 ) byte {
69+ return 1 << (index - b .getBlock (index )* blockSize )
6370}
6471
6572func (b * Bitmap ) Set (index uint64 ) {
66- if index > b . max {
73+ if index > MaxIndex {
6774 return
6875 }
6976
@@ -72,11 +79,15 @@ func (b *Bitmap) Set(index uint64) {
7279 defer b .mux .Unlock ()
7380 }
7481
75- b .data [index % b .size ] |= 1 << (index % blockSize )
82+ if index > b .max {
83+ b .resize (index )
84+ }
85+
86+ b .bits [b .getBlock (index )] |= b .getBit (index )
7687}
7788
7889func (b * Bitmap ) Del (index uint64 ) {
79- if index > b .max {
90+ if index > b .max || index > MaxIndex {
8091 return
8192 }
8293
@@ -85,11 +96,11 @@ func (b *Bitmap) Del(index uint64) {
8596 defer b .mux .Unlock ()
8697 }
8798
88- b .data [ index % b . size ] &^= 1 << (index % blockSize )
99+ b .bits [ b . getBlock ( index ) ] &^= b . getBit (index )
89100}
90101
91102func (b * Bitmap ) Has (index uint64 ) bool {
92- if index > b .max {
103+ if index > b .max || index > MaxIndex {
93104 return false
94105 }
95106
@@ -98,29 +109,49 @@ func (b *Bitmap) Has(index uint64) bool {
98109 defer b .mux .RUnlock ()
99110 }
100111
101- return (b .data [ index % b . size ] & ( 1 << ( index % blockSize ) )) > 0
112+ return (b .bits [ b . getBlock ( index ) ] & b . getBit ( index )) > 0
102113}
103114
104- func (b * Bitmap ) Dump () []byte {
115+ func (b * Bitmap ) MarshalBinary () ( []byte , error ) {
105116 if ! b .lockoff {
106117 b .mux .RLock ()
107118 defer b .mux .RUnlock ()
108119 }
109120
110- out := make ([]byte , b .size )
111- copy (out , b .data )
112- return out
121+ out := make ([]byte , b .blocks )
122+ copy (out , b .bits )
123+
124+ return out , nil
113125}
114126
115- func (b * Bitmap ) Restore (in []byte ) {
127+ func (b * Bitmap ) UnmarshalBinary (in []byte ) error {
116128 if ! b .lockoff {
117129 b .mux .Lock ()
118130 defer b .mux .Unlock ()
119131 }
120132
121- b .data = make ([]byte , len (in ))
122- copy (b .data , in )
133+ b .bits = make ([]byte , len (in ))
134+ copy (b .bits , in )
123135
124- b .size = uint64 (len (in ))
125- b .max = b .size * blockSize
136+ b .blocks = uint64 (len (in ))
137+ b .max = b .blocks * blockSize
138+
139+ return nil
140+ }
141+
142+ func (b * Bitmap ) CopyTo (dst * Bitmap ) {
143+ if ! b .lockoff {
144+ b .mux .Lock ()
145+ defer b .mux .Unlock ()
146+ }
147+ if ! dst .lockoff {
148+ dst .mux .Lock ()
149+ defer dst .mux .Unlock ()
150+ }
151+
152+ dst .bits = make ([]byte , len (b .bits ))
153+ copy (dst .bits , b .bits )
154+ dst .blocks = b .blocks
155+ dst .max = b .max
156+ dst .lockoff = b .lockoff
126157}
0 commit comments