forked from beevik/go6502
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsettings.go
125 lines (109 loc) · 3.2 KB
/
settings.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright 2018 Brett Vickers. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package host
import (
"errors"
"fmt"
"io"
"reflect"
"strings"
"github.com/beevik/prefixtree"
)
type settings struct {
HexMode bool `doc:"hexadecimal input mode"`
CompactMode bool `doc:"compact disassembly output"`
MemDumpBytes int `doc:"default number of memory bytes to dump"`
DisasmLines int `doc:"default number of lines to disassemble"`
SourceLines int `doc:"default number of source lines to display"`
MaxStepLines int `doc:"max lines to disassemble when stepping"`
NextDisasmAddr uint16 `doc:"address of next disassembly"`
NextSourceAddr uint16 `doc:"address of next source line display"`
NextMemDumpAddr uint16 `doc:"address of next memory dump"`
}
func newSettings() *settings {
return &settings{
HexMode: false,
CompactMode: false,
MemDumpBytes: 64,
DisasmLines: 10,
SourceLines: 10,
MaxStepLines: 20,
NextDisasmAddr: 0,
NextMemDumpAddr: 0,
}
}
type settingsField struct {
name string
index int
kind reflect.Kind
typ reflect.Type
doc string
}
var (
settingsTree = prefixtree.New()
settingsFields []settingsField
)
func init() {
/* LogFile, err := os.OpenFile("6502Emu.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Fatal("Failed to open log file:", err)
}
infoLogger := log.New(LogFile, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile) */
settingsType := reflect.TypeOf(settings{})
settingsFields = make([]settingsField, settingsType.NumField())
for i := 0; i < len(settingsFields); i++ {
f := settingsType.Field(i)
doc, _ := f.Tag.Lookup("doc")
settingsFields[i] = settingsField{
name: f.Name,
index: i,
kind: f.Type.Kind(),
typ: f.Type,
doc: doc,
}
settingsTree.Add(strings.ToLower(f.Name), &settingsFields[i])
}
}
func (s *settings) Display(w io.Writer) {
value := reflect.ValueOf(s).Elem()
for i, f := range settingsFields {
v := value.Field(i)
var s string
switch f.kind {
case reflect.String:
s = fmt.Sprintf(" %-16s \"%s\"", f.name, v.String())
case reflect.Uint8:
s = fmt.Sprintf(" %-16s $%02X", f.name, uint8(v.Uint()))
case reflect.Uint16:
s = fmt.Sprintf(" %-16s $%04X", f.name, uint16(v.Uint()))
default:
s = fmt.Sprintf(" %-16s %v", f.name, v)
}
fmt.Fprintf(w, "%-28s (%s)\n", s, f.doc)
}
}
func (s *settings) Kind(key string) reflect.Kind {
f, err := settingsTree.FindValue(strings.ToLower(key))
if err != nil {
return reflect.Invalid
}
return f.(*settingsField).kind
}
func (s *settings) Set(key string, value any) error {
ff, err := settingsTree.FindValue(strings.ToLower(key))
if err != nil {
return err
}
f := ff.(*settingsField)
vIn := reflect.ValueOf(value)
if (f.kind == reflect.String && vIn.Type().Kind() != reflect.String) ||
(f.kind != reflect.String && vIn.Type().Kind() == reflect.String) ||
!vIn.Type().ConvertibleTo(f.typ) {
return errors.New("invalid type")
}
vInConverted := vIn.Convert(f.typ)
vOut := reflect.ValueOf(s).Elem().Field(f.index).Addr().Elem()
vOut.Set(vInConverted)
return nil
}