/
context.go
91 lines (82 loc) · 1.61 KB
/
context.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
package model
import (
"reflect"
"strconv"
"github.com/goui2/ui/com"
)
type context struct {
model Model
path Path
}
func NewContext(m Model, s string) com.Context {
p := NewPath(s)
if !p.IsAbsolut() {
panic("path is not absolute: " + p.String())
}
return &context{
model: m,
path: p,
}
}
func (c *context) GetModel() interface{} {
return c.model
}
func (c *context) GetObject(s string) interface{} {
if v := c.GetValue(s); v.IsValid() {
return v.Interface()
} else {
return nil
}
}
var (
reflectInvalid = reflect.ValueOf(nil)
)
func (c *context) GetValue(sp string) (val com.Value) {
p := NewPath(sp)
var rv, pv reflect.Value
rv = reflect.ValueOf(nil)
pv = rv
v := c.GetModel().(Model).GetObject()
if v == nil {
return Value{reflectInvalid, "", reflectInvalid, c}
}
var ok bool
var s string
defer func() {
if t := recover(); t != nil {
val = Value{pv, s, reflectInvalid, c}
}
}()
dp := c.path.Append(p)
if rv, ok = v.(reflect.Value); !ok {
rv = reflect.ValueOf(v)
}
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
for idx, _ := range dp[1:] {
pv = rv
s = dp.Name(uint8(idx + 1))
switch k := rv.Kind(); k {
case reflect.Struct:
rv = rv.FieldByName(s)
case reflect.Map:
rv = rv.MapIndex(reflect.ValueOf(s))
if rv.IsValid() {
rv = rv.Elem()
}
case reflect.Array, reflect.Slice:
if idx, err := strconv.Atoi(s); err == nil {
rv = rv.Index(idx)
} else {
return Value{pv, s, reflectInvalid, c}
}
default:
return Value{pv, s, reflectInvalid, c}
}
}
return Value{pv, s, rv, c}
}
func (c *context) GetPath() string {
return c.path.String()
}