github.com/hernad/nomad@v1.6.112/nomad/structs/bitmap.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package structs 5 6 import ( 7 "fmt" 8 9 "golang.org/x/exp/slices" 10 ) 11 12 // Bitmap is a simple uncompressed bitmap 13 type Bitmap []byte 14 15 // NewBitmap returns a bitmap with up to size indexes 16 func NewBitmap(size uint) (Bitmap, error) { 17 if size == 0 { 18 return nil, fmt.Errorf("bitmap must be positive size") 19 } 20 if size&7 != 0 { 21 return nil, fmt.Errorf("bitmap must be byte aligned") 22 } 23 b := make([]byte, size>>3) 24 return Bitmap(b), nil 25 } 26 27 // Copy returns a copy of the Bitmap 28 func (b Bitmap) Copy() (Bitmap, error) { 29 if b == nil { 30 return nil, fmt.Errorf("can't copy nil Bitmap") 31 } 32 33 raw := make([]byte, len(b)) 34 copy(raw, b) 35 return Bitmap(raw), nil 36 } 37 38 // Size returns the size of the bitmap 39 func (b Bitmap) Size() uint { 40 return uint(len(b) << 3) 41 } 42 43 // Set is used to set the given index of the bitmap 44 func (b Bitmap) Set(idx uint) { 45 bucket := idx >> 3 46 mask := byte(1 << (idx & 7)) 47 b[bucket] |= mask 48 } 49 50 // Unset is used to unset the given index of the bitmap 51 func (b Bitmap) Unset(idx uint) { 52 bucket := idx >> 3 53 // Mask should be all ones minus the idx position 54 offset := 1 << (idx & 7) 55 mask := byte(offset ^ 0xff) 56 b[bucket] &= mask 57 } 58 59 // Check is used to check the given index of the bitmap 60 func (b Bitmap) Check(idx uint) bool { 61 bucket := idx >> 3 62 mask := byte(1 << (idx & 7)) 63 return (b[bucket] & mask) != 0 64 } 65 66 // Clear is used to efficiently clear the bitmap 67 func (b Bitmap) Clear() { 68 for i := range b { 69 b[i] = 0 70 } 71 } 72 73 // IndexesInRange returns the indexes in which the values are either set or unset based 74 // on the passed parameter in the passed range 75 func (b Bitmap) IndexesInRange(set bool, from, to uint) []int { 76 var indexes []int 77 for i := from; i <= to && i < b.Size(); i++ { 78 c := b.Check(i) 79 if c && set || !c && !set { 80 indexes = append(indexes, int(i)) 81 } 82 } 83 84 return indexes 85 } 86 87 // IndexesInRangeFiltered returns the indexes in which the values are either set 88 // or unset based on the passed parameter in the passed range, and do not appear 89 // in the filter slice 90 func (b Bitmap) IndexesInRangeFiltered(set bool, from, to uint, filter []int) []int { 91 var indexes []int 92 for i := from; i <= to && i < b.Size(); i++ { 93 c := b.Check(i) 94 if c == set { 95 if len(filter) < 1 || !slices.Contains(filter, int(i)) { 96 indexes = append(indexes, int(i)) 97 } 98 } 99 } 100 101 return indexes 102 } 103 104 // String represents the Bitmap the same as slice of the Bitmap's set values 105 func (b Bitmap) String() string { 106 return fmt.Sprintf("%v", b.IndexesInRange(true, 0, b.Size())) 107 }