-
Notifications
You must be signed in to change notification settings - Fork 4
/
decode.go
129 lines (114 loc) · 2.68 KB
/
decode.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
package tmsh
import (
"fmt"
"reflect"
"strconv"
"strings"
)
// Unmarshal parses the 'field-fmt' formatted data and stores the result in the value pointed to by out.
func Unmarshal(data string, out interface{}) error {
data = strings.Trim(data, "\n")
l := Lexer{s: newScanner(data)}
if yyParse(&l) != 0 {
return fmt.Errorf("Parse error")
}
v := reflect.ValueOf(out)
if v.Kind() == reflect.Ptr && !v.IsNil() {
v = v.Elem()
}
unmarshal(l.result, v)
return nil
}
func unmarshal(n *node, out reflect.Value) {
switch n.kind {
case ltmNode:
// Store LTM components info into embedded struct
for i := 0; i < out.NumField(); i++ {
fieldValue := out.Field(i)
if fieldValue.Kind() == reflect.Struct {
unmarshal(n.children[0], fieldValue)
}
}
// Store LTM components info into each struct fields
unmarshal(n.children[0], out)
// Set name field
if f, ok := lookupField("name", out); ok {
if f.Kind() == reflect.String && f.String() == "" {
f.SetString(n.value)
}
}
// Set component field
if f, ok := lookupField("component", out); ok {
if f.Kind() == reflect.String && f.String() == "" {
f.SetString(n.component)
}
}
case structNode:
decodeStructNode(n, out)
case keyNode:
decodeKeyNode(n, out)
case scalarNode:
decodeScalarNode(n, out)
default:
panic("Unknown node kind")
}
}
func decodeStructNode(n *node, out reflect.Value) {
l := len(n.children)
switch out.Kind() {
case reflect.Struct:
for _, c := range n.children {
unmarshal(c, out)
}
case reflect.Slice:
out.Set(reflect.MakeSlice(out.Type(), l, l))
et := out.Type().Elem()
for i := 0; i < l; i++ {
e := reflect.New(et).Elem()
for _, c := range n.children[i].children {
unmarshal(c, e)
}
out.Index(i).Set(e)
}
case reflect.Map:
out.Set(reflect.MakeMap(out.Type()))
et := out.Type().Elem()
for i := 0; i < l; i++ {
k := reflect.ValueOf(n.children[i].value)
v := reflect.New(et).Elem()
for _, c := range n.children[i].children {
unmarshal(c, v)
}
out.SetMapIndex(k, v)
}
}
}
func decodeKeyNode(n *node, out reflect.Value) {
switch out.Kind() {
case reflect.Struct:
if f, ok := lookupField(n.value, out); ok {
if len(n.children) > 0 {
unmarshal(n.children[0], f)
}
}
}
}
func decodeScalarNode(n *node, out reflect.Value) {
switch out.Kind() {
case reflect.Int:
i, _ := strconv.ParseInt(n.value, 10, 64)
out.SetInt(i)
case reflect.String:
out.SetString(n.value)
}
}
func lookupField(tag string, v reflect.Value) (reflect.Value, bool) {
typ := v.Type()
for i := 0; i < v.NumField(); i++ {
fi := typ.Field(i)
if fi.Tag.Get("ltm") == tag {
return v.Field(i), true
}
}
return reflect.Value{}, false
}