-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpath.go
98 lines (84 loc) · 1.74 KB
/
path.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
package tmpl
import (
"bytes"
"fmt"
"reflect"
"strings"
)
type pathItem struct {
val reflect.Value
name string
}
type path []pathItem
func pathRootedAt(v interface{}) path {
return path{pathItem{
name: "/",
val: reflect.ValueOf(v),
}}
}
func (p path) String() string {
if len(p) == 1 {
return "/."
}
buf := bytes.NewBufferString("/")
for _, it := range p[1:] {
fmt.Fprintf(buf, ".%s", it.name)
}
return buf.String()
}
func (p path) StringWith(its []string) string {
if len(p) == 1 {
return fmt.Sprintf("/.%s", strings.Join(its, "."))
}
return fmt.Sprintf("%s.%s", p, strings.Join(its, "."))
}
func (p path) itemBehind(num int) (i pathItem, err error) {
if num < 0 || num >= len(p) {
err = fmt.Errorf("%q can't pop %d items off", p, num)
return
}
i = p[len(p)-(num+1)]
return
}
func (p *path) push(i pathItem) {
*p = append(*p, i)
}
func (p *path) pop(num int) (err error) {
if num < 0 || num >= len(*p) {
err = fmt.Errorf("%q cant pop %d items off", p, num)
return
}
*p = (*p)[:len(*p)-(num)]
return
}
func (p path) lastValue() reflect.Value {
return p[len(p)-1].val
}
func (p path) dup() (d path) {
d = make(path, len(p))
copy(d, p)
return
}
func (p *path) cd(keys []string, set map[string]reflect.Value) error {
for _, key := range keys {
val, err := access(*p, p.lastValue(), key, set)
if err != nil {
return err
}
p.push(pathItem{
name: key,
val: val,
})
}
return nil
}
func (p path) valueAt(keys []string, set map[string]reflect.Value) (v reflect.Value, err error) {
v = p.lastValue()
for i, key := range keys {
v, err = access(p, v, key, set)
if err != nil {
return v, fmt.Errorf("%s%s: Error accessing item %d: %q", p, strings.Join(keys[:i+1], "."), i, key)
}
}
return
}