internal/bitmap/bitmap.go (55 lines of code) (raw):

package bitmap import ( "math/bits" ) // bitmap is a lazily initialized bitmap type Bitmap struct { max uint32 bits []uint64 } func New(max uint32) *Bitmap { return &Bitmap{max: max} } // add sets n in the bitmap. // // bits will be expanded as needed. // // If n is greater than max, the call has no effect. func (b *Bitmap) Add(n uint32) { if n > b.max { return } var ( idx = n / 64 offset = n % 64 ) if l := len(b.bits); int(idx) >= l { b.bits = append(b.bits, make([]uint64, int(idx)-l+1)...) } b.bits[idx] |= 1 << offset } // remove clears n from the bitmap. // // If n is not set or greater than max the call has not effect. func (b *Bitmap) Remove(n uint32) { var ( idx = n / 64 offset = n % 64 ) if int(idx) >= len(b.bits) { return } b.bits[idx] &= ^uint64(1 << offset) } // next sets and returns the lowest unset bit in the bitmap. // // bits will be expanded if necessary. // // If there are no unset bits below max, the second return // value will be false. func (b *Bitmap) Next() (uint32, bool) { // find the first unset bit for i, v := range b.bits { // skip if all bits are set if v == ^uint64(0) { continue } var ( offset = bits.TrailingZeros64(^v) // invert and count zeroes next = uint32(i*64 + offset) ) // check if in bounds if next > b.max { return next, false } // set bit b.bits[i] |= 1 << uint32(offset) return next, true } // no unset bits in the current slice, // check if the full range has been allocated if uint64(len(b.bits)*64) > uint64(b.max) { return 0, false } // full range not allocated, append entry with first // bit set b.bits = append(b.bits, 1) // return the value of the first bit return uint32(len(b.bits)-1) * 64, true }