boolmap - nibblemap.go
1 package boolmap
2
3 // NibbleMap is a map of Nibbles (4-bits, values 0-15)
4 type NibbleMap map[uint64]byte
5
6 // NewNibbleMap return a new, initialised, NibbleMap
7 func NewNibbleMap() NibbleMap {
8 return make(NibbleMap)
9 }
10
11 // Get returns a crumb from the given position
12 func (n NibbleMap) Get(p uint64) byte {
13 d := n[p>>1]
14 if p&1 == 0 {
15 return d & 15
16 }
17 return d >> 4
18 }
19
20 // Set sets the crumb at the given position
21 func (n NibbleMap) Set(p uint64, d byte) {
22 pos := p >> 1
23 oldData, ok := n[pos]
24 if !ok && d == 0 {
25 return
26 }
27 if p&1 == 0 {
28 d = oldData&240 | d&15
29 } else {
30 d = oldData&15 | d<<4
31 }
32 if d == 0 {
33 delete(n, pos)
34 } else {
35 n[pos] = d
36 }
37 }
38
39 // NibbleSlice is a slice of bytes representing nibbles (4-bits)
40 type NibbleSlice []byte
41
42 // NewNibbleSlice returns a new, initialised, CrumbSlice
43 func NewNibbleSlice() NibbleSlice {
44 return NewNibbleSliceSize(1)
45 }
46
47 // NewNibbleSliceSize returns a new NibbleSlice, initialised to the given size
48 func NewNibbleSliceSize(size uint) NibbleSlice {
49 sliceSize := size >> 1
50 if size&1 != 0 {
51 sliceSize++
52 }
53 return make(NibbleSlice, sliceSize)
54 }
55
56 // Get returns a crumb from the given position
57 func (n NibbleSlice) Get(p uint) byte {
58 pos := p >> 1
59 if pos >= uint(len(n)) {
60 return 0
61 }
62 d := n[pos]
63 if p&1 == 0 {
64 return d & 15
65 }
66 return d >> 4
67 }
68
69 // Set sets the crumb at the given position
70 func (n *NibbleSlice) Set(p uint, d byte) {
71 pos := p >> 1
72 if pos >= uint(len(*n)) {
73 if d == 0 {
74 return
75 }
76 if pos < uint(cap(*n)) {
77 *n = (*n)[:cap(*n)]
78 } else {
79 var newData NibbleSlice
80 if pos < 512 {
81 newData = make([]byte, pos<<1)
82 } else {
83 newData = make([]byte, pos+(pos>>2))
84 }
85 copy(newData, *n)
86 *n = newData
87 }
88 }
89 oldData := (*n)[pos]
90 if p&1 == 0 {
91 d = oldData&240 | d&15
92 } else {
93 d = oldData&15 | d<<4
94 }
95 (*n)[pos] = d
96 }