Add bit flag manipulation

This commit is contained in:
lash 2023-03-31 23:17:44 +01:00
parent f7bcf8896b
commit a6b57c92a9
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
2 changed files with 134 additions and 6 deletions

View File

@ -27,15 +27,16 @@ type State struct {
execPath []string // Command symbols stack execPath []string // Command symbols stack
arg *string // Optional argument. Nil if not set. arg *string // Optional argument. Nil if not set.
sizes map[string]uint16 // Size limits for all loaded symbols. sizes map[string]uint16 // Size limits for all loaded symbols.
sink *string // sink *string // Sink symbol set for level
bitSize uint32 // size of (32-bit capacity) bit flag byte array
//sizeIdx uint16 //sizeIdx uint16
} }
// NewState creates a new State object with bitSize number of error condition states. // NewState creates a new State object with bitSize number of error condition states.
func NewState(bitSize uint64) State { func NewState(bitSize uint32) State {
if bitSize == 0 { if bitSize == 0 {
panic("bitsize cannot be 0") panic("bitsize cannot be 0")
} }
n := bitSize % 8 n := bitSize % 8
if n > 0 { if n > 0 {
bitSize += (8 - n) bitSize += (8 - n)
@ -45,11 +46,63 @@ func NewState(bitSize uint64) State {
Flags: make([]byte, bitSize / 8), Flags: make([]byte, bitSize / 8),
CacheSize: 0, CacheSize: 0,
CacheUseSize: 0, CacheUseSize: 0,
bitSize: bitSize,
} }
st.Down("") st.Down("")
return st return st
} }
// SetFlag sets the flag at the given bit field index.
//
// Returns true if bit state was changed.
//
// Fails if bitindex is out of range.
func(st *State) SetFlag(bitIndex uint32) (bool, error) {
if bitIndex + 1 > st.bitSize {
return false, fmt.Errorf("bit index %v is out of range of bitfield size %v", bitIndex, st.bitSize)
}
r :=st.getFlag(bitIndex)
if r {
return false, nil
}
byteIndex := bitIndex / 8
localBitIndex := bitIndex % 8
b := st.Flags[byteIndex]
st.Flags[byteIndex] = b | (1 << localBitIndex)
return true, nil
}
// ResetFlag resets the flag at the given bit field index.
//
// Returns true if bit state was changed.
//
// Fails if bitindex is out of range.
func(st *State) ResetFlag(bitIndex uint32) (bool, error) {
if bitIndex + 1 > st.bitSize {
return false, fmt.Errorf("bit index %v is out of range of bitfield size %v", bitIndex, st.bitSize)
}
r :=st.getFlag(bitIndex)
if !r {
return false, nil
}
byteIndex := bitIndex / 8
localBitIndex := bitIndex % 8
b := st.Flags[byteIndex]
st.Flags[byteIndex] = b & (^(1 << localBitIndex))
return true, nil
}
// GetFlag returns the state of the flag at the given bit field index.
//
// Fails if bit field index is out of range.
func(st *State) GetFlag(bitIndex uint32) (bool, error) {
if bitIndex + 1 > st.bitSize {
return false, fmt.Errorf("bit index %v is out of range of bitfield size %v", bitIndex, st.bitSize)
}
return st.getFlag(bitIndex), nil
}
// WithCacheSize applies a cumulative cache size limitation for all cached items. // WithCacheSize applies a cumulative cache size limitation for all cached items.
func(st State) WithCacheSize(cacheSize uint32) State { func(st State) WithCacheSize(cacheSize uint32) State {
st.CacheSize = cacheSize st.CacheSize = cacheSize
@ -288,7 +341,16 @@ func(st *State) checkCapacity(v string) uint32 {
return sz return sz
} }
// flush relveant properties for level change
func(st *State) resetCurrent() { func(st *State) resetCurrent() {
st.sink = nil st.sink = nil
st.CacheMap = make(map[string]string) st.CacheMap = make(map[string]string)
} }
// Retrieve the state of a state flag
func(st *State) getFlag(bitIndex uint32) bool {
byteIndex := bitIndex / 8
localBitIndex := bitIndex % 8
b := st.Flags[byteIndex]
return (b & (1 << localBitIndex)) > 0
}

View File

@ -4,8 +4,8 @@ import (
"testing" "testing"
) )
// Check creation and testing of state flags // Check creation
func TestNewStateFlags(t *testing.T) { func TestNewState(t *testing.T) {
st := NewState(5) st := NewState(5)
if len(st.Flags) != 1 { if len(st.Flags) != 1 {
t.Errorf("invalid state flag length: %v", len(st.Flags)) t.Errorf("invalid state flag length: %v", len(st.Flags))
@ -17,7 +17,73 @@ func TestNewStateFlags(t *testing.T) {
st = NewState(17) st = NewState(17)
if len(st.Flags) != 3 { if len(st.Flags) != 3 {
t.Errorf("invalid state flag length: %v", len(st.Flags)) t.Errorf("invalid state flag length: %v", len(st.Flags))
}
}
func TestStateFlags(t *testing.T) {
st := NewState(17)
v, err := st.GetFlag(2)
if err != nil {
t.Error(err)
}
if v {
t.Errorf("Expected bit 2 not to be set")
}
v, err = st.SetFlag(2)
if err != nil {
t.Error(err)
}
if !v {
t.Errorf("Expected change to be set for bit 2")
}
v, err = st.GetFlag(2)
if err != nil {
t.Error(err)
}
if !v {
t.Errorf("Expected bit 2 to be set")
}
v, err = st.SetFlag(10)
if err != nil {
t.Error(err)
}
if !v {
t.Errorf("Expected change to be set for bit 10")
}
v, err = st.GetFlag(10)
if err != nil {
t.Error(err)
}
if !v {
t.Errorf("Expected bit 10 to be set")
}
v, err = st.ResetFlag(2)
if err != nil {
t.Error(err)
}
if !v {
t.Errorf("Expected change to be set for bit 10")
}
v, err = st.GetFlag(2)
if err != nil {
t.Error(err)
}
if v {
t.Errorf("Expected bit 2 not to be set")
}
v, err = st.GetFlag(10)
if err != nil {
t.Error(err)
}
if !v {
t.Errorf("Expected bit 10 to be set")
}
v, err = st.SetFlag(10)
if err != nil {
t.Error(err)
}
if v {
t.Errorf("Expected change not to be set for bit 10")
} }
} }