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  }