go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

commit a6b57c92a9af102c5e630935b7fb5923296970be
parent f7bcf8896b3ee4ca75071300bd1e8563219d862d
Author: lash <dev@holbrook.no>
Date:   Fri, 31 Mar 2023 23:17:44 +0100

Add bit flag manipulation

Diffstat:
Mgo/state/state.go | 68+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mgo/state/state_test.go | 72+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
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") } }