commit 5b0fef09239aecf1d68cac0204fdd924fbbb9f47
parent c084ded406f3a3433b0f4fe0dc69f8c04ab92b09
Author: lash <dev@holbrook.no>
Date: Mon, 17 Apr 2023 16:31:43 +0100
Merge branch 'dev-0.0.9a' into dev-0.0.9
Diffstat:
4 files changed, 135 insertions(+), 9 deletions(-)
diff --git a/state/debug.go b/state/debug.go
@@ -0,0 +1,51 @@
+package state
+
+import (
+ "fmt"
+ "strings"
+)
+
+type flagDebugger struct {
+ flagStrings map[uint32]string
+}
+
+func newFlagDebugger() flagDebugger {
+ fd := flagDebugger{
+ flagStrings: make(map[uint32]string),
+ }
+ fd.register(FLAG_READIN, "INTERNAL_READIN")
+ fd.register(FLAG_INMATCH, "INTERNAL_INMATCH")
+ fd.register(FLAG_TERMINATE, "INTERNAL_TERMINATE")
+ fd.register(FLAG_DIRTY, "INTERNAL_DIRTY")
+ fd.register(FLAG_WAIT, "INTERNAL_WAIT")
+ fd.register(FLAG_LOADFAIL, "INTERNAL_LOADFAIL")
+ return fd
+}
+
+func(fd *flagDebugger) register(flag uint32, name string) {
+ fd.flagStrings[flag] = name
+}
+
+func(fd *flagDebugger) Register(flag uint32, name string) error {
+ if (flag < 8) {
+ return fmt.Errorf("flag %v is not definable by user", flag)
+ }
+ fd.register(flag, name)
+ return nil
+}
+
+func(fd *flagDebugger) AsString(flags []byte, length uint32) string {
+ var r []string
+ var i uint32
+ for i = 0; i < length + 8; i++ {
+ if getFlag(i, flags) {
+ s := fmt.Sprintf("%s(%v)", fd.flagStrings[i], i)
+ r = append(r, s)
+ }
+ }
+ return strings.Join(r, ",")
+}
+
+var (
+ FlagDebugger = newFlagDebugger()
+)
diff --git a/state/debug_test.go b/state/debug_test.go
@@ -0,0 +1,57 @@
+package state
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestDebugFlagDenied(t *testing.T) {
+ err := FlagDebugger.Register(7, "foo")
+ if err == nil {
+ t.Fatalf("expected error")
+ }
+}
+
+func TestDebugFlagString(t *testing.T) {
+ err := FlagDebugger.Register(8, "FOO")
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = FlagDebugger.Register(9, "BAR")
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = FlagDebugger.Register(11, "BAZ")
+ if err != nil {
+ t.Fatal(err)
+ }
+ flags := []byte{0x06, 0x09}
+ r := FlagDebugger.AsString(flags, 4)
+ expect := "INTERNAL_INMATCH(1),INTERNAL_TERMINATE(2),FOO(8),BAZ(11)"
+ if r != expect {
+ t.Fatalf("expected '%s', got '%s'", expect, r)
+ }
+}
+
+func TestDebugState(t *testing.T) {
+ err := FlagDebugger.Register(8, "FOO")
+ if err != nil {
+ t.Fatal(err)
+ }
+ st := NewState(1).WithDebug()
+ _, err = st.SetFlag(FLAG_DIRTY)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = st.SetFlag(8)
+ if err != nil {
+ t.Fatal(err)
+ }
+ st.Down("root")
+
+ r := fmt.Sprintf("%s", st)
+ expect := "moves: 1 idx: 0 flags: INTERNAL_DIRTY(3),FOO(8) path: root"
+ if r != expect {
+ t.Fatalf("expected '%s', got '%s'", expect, r)
+ }
+}
diff --git a/state/flag.go b/state/flag.go
@@ -20,5 +20,11 @@ func IsWriteableFlag(flag uint32) bool {
return false
}
-type FlagDebugger struct {
+// 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
}
+
diff --git a/state/state.go b/state/state.go
@@ -36,6 +36,7 @@ type State struct {
Flags []byte // Error state
Moves uint32 // Number of times navigation has been performed
input []byte // Last input
+ debug bool // Make string representation more human friendly
}
// number of bytes necessary to represent a bitfield of the given size.
@@ -50,13 +51,13 @@ func toByteSize(BitSize uint32) uint8 {
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
-}
+//// 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 in ADDITION to the 8 builtin flags.
func NewState(BitSize uint32) State {
@@ -72,6 +73,11 @@ func NewState(BitSize uint32) State {
return st
}
+func(st State) WithDebug() State {
+ st.debug = true
+ return st
+}
+
// SetFlag sets the flag at the given bit field index
//
// Returns true if bit state was changed.
@@ -342,7 +348,13 @@ func(st *State) Restart() error {
// String implements String interface
func(st State) String() string {
- return fmt.Sprintf("moves %v idx %v flags: 0x%x path: %s", st.Moves, st.SizeIdx, st.Flags, strings.Join(st.ExecPath, "/"))
+ var flags string
+ if st.debug {
+ flags = FlagDebugger.AsString(st.Flags, st.BitSize - 8)
+ } else {
+ flags = fmt.Sprintf("0x%x", st.Flags)
+ }
+ return fmt.Sprintf("moves: %v idx: %v flags: %s path: %s", st.Moves, st.SizeIdx, flags, strings.Join(st.ExecPath, "/"))
}
// initializes all flags not in control of client.