-
Notifications
You must be signed in to change notification settings - Fork 114
/
parser_cmd.go
139 lines (123 loc) · 2.69 KB
/
parser_cmd.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
128
129
130
131
132
133
134
135
136
137
138
139
package antnet
import (
"reflect"
"strings"
)
type CmdMatchType int
const (
CmdMatchTypeK CmdMatchType = iota
CmdMatchTypeKV
)
type cmdParseNode struct {
match CmdMatchType
kind reflect.Kind
index int
name string
c2sFunc ParseFunc
s2cFunc ParseFunc
next map[string]*cmdParseNode
prev *cmdParseNode
}
type CmdParser struct {
*Parser
node *cmdParseNode
values []interface{}
match CmdMatchType
}
func (r *CmdParser) ParseC2S(msg *Message) (IMsgParser, error) {
p, ok := r.parserString(string(msg.Data))
if ok {
return p, nil
}
return nil, ErrCmdUnPack
}
func (r *CmdParser) PackMsg(v interface{}) []byte {
data, _ := JsonPack(v)
return data
}
func (r *CmdParser) GetRemindMsg(err error, t MsgType) *Message {
if t == MsgTypeMsg {
return nil
} else {
return nil
}
}
func (r *CmdParser) parserString(s string) (IMsgParser, bool) {
if r.node == nil {
r.node = r.cmdRoot
}
s = strings.TrimSpace(s)
cmds := strings.Split(s, " ")
for _, v := range cmds {
if r.match == CmdMatchTypeK {
node, ok := r.node.next[v]
if !ok {
return nil, false
}
r.node = node
if node.match == CmdMatchTypeK {
continue
} else {
r.match = CmdMatchTypeKV
continue
}
}
i, err := ParseBaseKind(r.node.kind, v)
if err != nil {
return nil, false
}
r.match = CmdMatchTypeK
r.values = append(r.values, i)
}
if r.node.next == nil {
typ := reflect.ValueOf(r.node.c2sFunc())
ins := typ.Elem()
i := len(r.values)
s2cFunc := r.node.s2cFunc
for r.node != nil {
if r.node.match == CmdMatchTypeKV {
ins.Field(r.node.index).Set(reflect.ValueOf(r.values[i-1]))
i--
} else if r.node.kind == reflect.String && r.node != r.cmdRoot {
ins.Field(r.node.index).SetString(r.node.name)
}
r.node = r.node.prev
}
return &MsgParser{c2s: typ.Interface(), parser: r, s2cFunc: s2cFunc}, true
}
return nil, false
}
func registerCmdParser(root *cmdParseNode, c2sFunc ParseFunc, s2cFunc ParseFunc) {
msgType := reflect.TypeOf(c2sFunc())
if msgType == nil || msgType.Kind() != reflect.Ptr {
LogFatal("message pointer required")
return
}
typ := msgType.Elem()
prevRoute := root
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
name := strings.ToLower(field.Name)
tag := field.Tag
if prevRoute.next == nil {
prevRoute.next = map[string]*cmdParseNode{}
}
c, ok := prevRoute.next[name]
if !ok {
c = &cmdParseNode{}
c.prev = prevRoute
if tag.Get("match") == "k" {
c.match = CmdMatchTypeK
} else {
c.match = CmdMatchTypeKV
}
c.name = name
c.kind = field.Type.Kind()
c.index = i
prevRoute.next[name] = c
}
prevRoute = c
}
prevRoute.s2cFunc = s2cFunc
prevRoute.c2sFunc = c2sFunc
}