1 // Package boolmap creates a map of bools using bytes for efficiency (needs benchmarking for memory) 2 package boolmap // import "vimagination.zapto.org/boolmap" 3 4 // Map is the default boolmap 5 type Map map[uint64]byte 6 7 // NewMap returns a new, initialised Map 8 func NewMap() Map { 9 return make(Map) 10 } 11 12 // Get returns a bool, represented by a byte, for the specified position 13 func (m Map) Get(p uint64) byte { 14 if m.GetBool(p) { 15 return 1 16 } 17 return 0 18 } 19 20 // GetBool returns a bool for the specified position 21 func (m Map) GetBool(p uint64) bool { 22 return m[p>>3]&(1<<(p&7)) != 0 23 } 24 25 // Set sets a bool, represented by a byte, at the specified position 26 func (m Map) Set(p uint64, d byte) { 27 m.SetBool(p, d != 0) 28 } 29 30 // SetBool sets a bool at the specified position 31 func (m Map) SetBool(p uint64, d bool) { 32 shift := byte(1 << (p & 7)) 33 pos := p >> 3 34 c, ok := m[pos] 35 if !ok && !d { 36 return 37 } 38 if d { 39 c |= shift 40 } else { 41 c &^= shift 42 } 43 if c == 0 { 44 delete(m, pos) 45 } else { 46 m[pos] = c 47 } 48 } 49 50 // Slice is a slice of bytes representing bools 51 type Slice []byte 52 53 // NewSlice returnns a new, initialised Slice 54 func NewSlice() *Slice { 55 return NewSliceSize(1) 56 } 57 58 // NewSliceSize returns a new Slice, intitialised to the size given 59 func NewSliceSize(size uint) *Slice { 60 sliceSize := size >> 3 61 if size&7 != 0 { 62 sliceSize++ 63 } 64 s := make(Slice, sliceSize) 65 return &s 66 } 67 68 // Get returns a byte, representing a bool, at the specified position 69 func (s Slice) Get(p uint) byte { 70 if s.GetBool(p) { 71 return 1 72 } 73 return 0 74 } 75 76 // GetBool returns a bool for the specified position 77 func (s Slice) GetBool(p uint) bool { 78 pos := p >> 3 79 if pos > uint(len(s)) { 80 return false 81 } 82 return s[pos]&(1<<(p&7)) != 0 83 } 84 85 // Set sets a bool, given as a byte, at the specified position 86 func (s *Slice) Set(p uint, d byte) { 87 s.SetBool(p, d != 0) 88 } 89 90 // SetBool sets a bool at the specified position 91 func (s *Slice) SetBool(p uint, d bool) { 92 pos := p >> 3 93 if pos >= uint(len(*s)) { 94 if !d { 95 return 96 } 97 if pos < uint(cap(*s)) { 98 *s = (*s)[:cap(*s)] 99 } else { 100 var newData Slice 101 if pos < 512 { 102 newData = make(Slice, pos<<1) 103 } else { 104 newData = make(Slice, pos+(pos>>2)) 105 } 106 copy(newData, *s) 107 *s = newData 108 } 109 } 110 shift := byte(1 << (p & 7)) 111 if d { 112 (*s)[pos] |= shift 113 } else { 114 (*s)[pos] &^= shift 115 } 116 }