Add test state flag by byte slice

This commit is contained in:
lash 2023-04-01 08:36:26 +01:00
parent 3e5a7cf322
commit 324fd98cc3
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
2 changed files with 103 additions and 19 deletions

View File

@ -18,6 +18,8 @@ import (
// Symbols are loaded with individual size limitations. The limitations apply if a load symbol is updated. Symbols may be added with a 0-value for limits, called a "sink." If mapped, the sink will consume all net remaining size allowance unused by other symbols. Only one sink may be mapped per level.
//
// Symbol keys do not count towards cache size limitations.
//
// TODO factor out cache
type State struct {
Flags []byte // Error state
CacheSize uint32 // Total allowed cumulative size of values in cache
@ -32,22 +34,38 @@ type State struct {
//sizeIdx uint16
}
// NewState creates a new State object with bitSize number of error condition states.
func NewState(bitSize uint32) State {
func toByteSize(bitSize uint32) uint8 {
if bitSize == 0 {
panic("bitsize cannot be 0")
return 0
}
n := bitSize % 8
if n > 0 {
bitSize += (8 - n)
}
return uint8(bitSize / 8)
}
// Retrieve the state of a state flag
func getFlag(bitIndex uint32, bitField []byte) bool {
byteIndex := bitIndex / 8
localBitIndex := bitIndex % 8
b := bitField[byteIndex]
return (b & (1 << localBitIndex)) > 0
}
// NewState creates a new State object with bitSize number of error condition states.
func NewState(bitSize uint32) State {
st := State{
Flags: make([]byte, bitSize / 8),
CacheSize: 0,
CacheUseSize: 0,
bitSize: bitSize,
}
byteSize := toByteSize(bitSize)
if byteSize > 0 {
st.Flags = make([]byte, byteSize)
} else {
st.Flags = []byte{}
}
st.Down("")
return st
}
@ -61,7 +79,7 @@ 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)
r := getFlag(bitIndex, st.Flags)
if r {
return false, nil
}
@ -82,7 +100,7 @@ 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)
r := getFlag(bitIndex, st.Flags)
if !r {
return false, nil
}
@ -100,7 +118,46 @@ 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
return getFlag(bitIndex, st.Flags), nil
}
// FlagBitSize reports the amount of bits available in the bit field index.
func(st *State) FlagBitSize() uint32 {
return st.bitSize
}
// GetIndex scans a byte slice in same order as in storage, and returns the index of the first set bit.
//
// If the given byte slice is too small for the bit field bitsize, the check will terminate at end-of-data without error.
func(st *State) GetIndex(flags []byte) bool {
var globalIndex uint32
if st.bitSize == 0 {
return false
}
if len(flags) == 0 {
return false
}
var byteIndex uint8
var localIndex uint8
l := uint8(len(flags))
var i uint32
for i = 0; i < st.bitSize; i++ {
testVal := flags[byteIndex] & (1 << localIndex)
if (testVal & st.Flags[byteIndex]) > 0 {
return true
}
globalIndex += 1
if globalIndex % 8 == 0 {
byteIndex += 1
localIndex = 0
if byteIndex > (l - 1) {
return false
}
} else {
localIndex += 1
}
}
return false
}
// WithCacheSize applies a cumulative cache size limitation for all cached items.
@ -317,7 +374,6 @@ func(st *State) Size() (uint32, uint32) {
// return 0-indexed frame number where key is defined. -1 if not defined
func(st *State) frameOf(key string) int {
log.Printf("--- %s", key)
for i, m := range st.Cache {
for k, _ := range m {
if k == key {
@ -347,10 +403,3 @@ func(st *State) resetCurrent() {
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

@ -90,12 +90,47 @@ func TestStateFlags(t *testing.T) {
if err != nil {
t.Error(err)
}
v, err = st.SetFlag(19)
v, err = st.SetFlag(16)
if err != nil {
t.Error(err)
}
if !bytes.Equal(st.Flags[:3], []byte{0x04, 0x04, 0x08}) {
t.Errorf("Expected 0x020203, got %v", st.Flags[:3])
v, err = st.SetFlag(17)
if err == nil {
t.Errorf("Expected out of range for bit index 17")
}
if !bytes.Equal(st.Flags[:3], []byte{0x04, 0x04, 0x01}) {
t.Errorf("Expected 0x040401, got %v", st.Flags[:3])
}
}
func TestStateFlagFromSlice(t *testing.T) {
st := NewState(15)
_, _= st.SetFlag(2)
v := st.GetIndex([]byte{})
if v {
t.Errorf("Expected no match on empty compare")
}
v = st.GetIndex([]byte{0x01})
if v {
t.Errorf("Expected 0x01 not to match")
}
v = st.GetIndex([]byte{0x04})
if !v {
t.Errorf("Expected 0x04 to match")
}
_, _= st.SetFlag(12)
v = st.GetIndex([]byte{0x04})
if !v {
t.Errorf("Expected 0x04 to match")
}
v = st.GetIndex([]byte{0x00, 0x10})
if !v {
t.Errorf("Expected 0x1000 to match")
}
v, _ = st.ResetFlag(2)
v = st.GetIndex([]byte{0x00, 0x10})
if !v {
t.Errorf("Expected 0x1000 to matck")
}
}