-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathelement.go
127 lines (106 loc) · 2.53 KB
/
element.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
126
127
package config
import (
"bytes"
"reflect"
"strings"
)
func (cfg *Config) getElement(s string) error {
cfg.Lock()
defer cfg.Unlock()
s = strings.TrimSpace(s)
if !cfg.current.IsValid() {
if ok := cfg.fetchDirective(s); ok {
return nil
} else {
cfg.current = cfg.entry
}
}
cfg.restoreElement()
if cfg.current.Kind() != reflect.Struct {
return cfg.error("unknown directive %s, current kind is %s, but struct required", s, cfg.current.Kind())
}
// 如果是驼峰,就要处理一下
field := cfg.fixedField(s)
var ok bool
if cfg.typ, ok = cfg.current.Type().FieldByName(field); !ok {
cfg.popElement()
if cfg.current == cfg.entry {
if ok := cfg.fetchDirective(field); ok {
return nil
}
}
return cfg.error("unknown directive %s ", s)
}
cfg.current = cfg.current.FieldByName(field)
return nil
}
func (cfg *Config) fetchDirective(s string) bool {
if rev, ok := cfg.directives[s]; ok {
rev.Runnable = true
cfg.current = rev.config
cfg.fixedElement()
return true
}
return false
}
func (cfg *Config) getStruct() (reflect.Value, bool) {
if len(cfg.queue) < 1 {
return reflect.Value{}, false
}
return cfg.queue[len(cfg.queue)-1], true
}
func (cfg *Config) getMethod(s string) (reflect.Value, bool) {
if element, ok := cfg.getStruct(); ok {
if element.Kind() != reflect.Ptr && element.CanAddr() {
element = element.Addr()
}
fn := element.MethodByName(s)
if fn.IsValid() && fn.Kind() == reflect.Func {
return fn, true
}
}
return reflect.Value{}, false
}
func (cfg *Config) getNearestSlice() (reflect.Value, bool) {
if len(cfg.queue) < 2 {
return reflect.Value{}, false
}
return cfg.queue[len(cfg.queue)-2], true
}
func (cfg *Config) restoreElement() {
cfg.fixedElement()
cfg.queue = append(cfg.queue, cfg.current)
}
func (cfg *Config) fixedElement() {
if cfg.current.Kind() == reflect.Ptr {
if cfg.current.IsNil() {
cfg.current.Set(reflect.New(cfg.current.Type().Elem()))
}
cfg.current = cfg.current.Elem()
}
}
func (cfg *Config) pushElement(v reflect.Value) {
cfg.queue = append(cfg.queue, cfg.current)
cfg.current = v
}
func (cfg *Config) popElement() {
if len(cfg.queue) < 1 {
cfg.current = reflect.Value{}
return
}
cfg.current = cfg.queue[len(cfg.queue)-1]
cfg.queue = cfg.queue[:len(cfg.queue)-1]
}
func (cfg *Config) fixedField(s string) string {
if cfg.camel {
stmp := strings.Split(s, "_")
buffer := bytes.Buffer{}
for _, v := range stmp {
buffer.WriteString(strings.Title(v))
}
s = buffer.String()
} else {
s = strings.Title(s)
}
return s
}