commit a6b57c92a9af102c5e630935b7fb5923296970be
parent f7bcf8896b3ee4ca75071300bd1e8563219d862d
Author: lash <dev@holbrook.no>
Date: Fri, 31 Mar 2023 23:17:44 +0100
Add bit flag manipulation
Diffstat:
2 files changed, 134 insertions(+), 6 deletions(-)
diff --git a/go/state/state.go b/go/state/state.go
@@ -27,15 +27,16 @@ type State struct {
execPath []string // Command symbols stack
arg *string // Optional argument. Nil if not set.
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
}
// 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 {
panic("bitsize cannot be 0")
- }
+ }
n := bitSize % 8
if n > 0 {
bitSize += (8 - n)
@@ -45,11 +46,63 @@ func NewState(bitSize uint64) State {
Flags: make([]byte, bitSize / 8),
CacheSize: 0,
CacheUseSize: 0,
+ bitSize: bitSize,
}
st.Down("")
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.
func(st State) WithCacheSize(cacheSize uint32) State {
st.CacheSize = cacheSize
@@ -288,7 +341,16 @@ func(st *State) checkCapacity(v string) uint32 {
return sz
}
+// flush relveant properties for level change
func(st *State) resetCurrent() {
st.sink = nil
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
+}
diff --git a/go/state/state_test.go b/go/state/state_test.go
@@ -4,8 +4,8 @@ import (
"testing"
)
-// Check creation and testing of state flags
-func TestNewStateFlags(t *testing.T) {
+// Check creation
+func TestNewState(t *testing.T) {
st := NewState(5)
if len(st.Flags) != 1 {
t.Errorf("invalid state flag length: %v", len(st.Flags))
@@ -17,7 +17,73 @@ func TestNewStateFlags(t *testing.T) {
st = NewState(17)
if len(st.Flags) != 3 {
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")
}
}