-
-
Notifications
You must be signed in to change notification settings - Fork 36
/
slice.go
138 lines (113 loc) · 3.3 KB
/
slice.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
package dotpath
import (
"fmt"
"reflect"
"strconv"
"strings"
"github.com/pkg/errors"
)
func get_from_slice_by_path(IDX int, paths []string, data []interface{}) (interface{}, error) {
if data == nil {
return nil, errors.New("input data is nil")
}
header := fmt.Sprintf("get_from_slice_by_path: %d %v in:\n%+v\n\n", IDX, paths, data)
// fmt.Println(header)
logger.Debug(header)
if IDX >= len(paths) || len(paths) == 0 {
return nil, nil
}
subs := []interface{}{}
P := paths[IDX]
lpos_index := strings.Index(P, "[")
rpos_index := strings.LastIndex(P, "]")
pos_colon := strings.Index(P, ":")
has_listing := strings.Contains(P, ",")
// pos_regex := strings.Index(P, "regex")
has_eq := strings.Contains(P, "==")
// has_ne := strings.Contains(P, "!=")
inner := ""
if lpos_index > -1 {
inner = P[lpos_index+1 : rpos_index]
}
// fmt.Printf(" slice inner: %d %q %q\n", IDX, inner, P)
// handle indexing here
if inner != "" {
inner := P[lpos_index+1 : rpos_index]
// fmt.Printf("index: %q [%d:%d]\n", inner, lpos_index+1, rpos_index)
// handle slicing
if pos_colon > -1 {
elems, err := extract_from_slice_with_splice(inner, data)
if err != nil {
return nil, errors.Wrap(err, "while extracting splice in dotpath case []interface{}")
}
return elems, nil
}
// handle equality
if has_eq {
fields := strings.Split(inner, "==")
if len(fields) != 2 {
return nil, errors.New("Found not 2 fields in equality in: " + P)
}
elems, err := extract_from_slice_with_field(fields[0], fields[1], data)
if err != nil {
return nil, errors.Wrap(err, "while extracting has_eq in dotpath case []interface{}")
}
return elems, nil
}
// handle listing
if has_listing {
elems, err := extract_from_slice_with_name(inner, data)
if err != nil {
return nil, errors.Wrap(err, "while extracting listing in dotpath case []interface{}")
}
return elems, nil
}
// handle int
i_val, ierr := strconv.Atoi(inner)
if ierr == nil {
if i_val < 0 || i_val >= len(data) {
str := "index out of range: " + inner
return str, errors.New(str)
}
return data[i_val], nil
}
// default is single string for name, then field
elems, err := extract_from_slice_with_name(inner, data)
if err != nil {
return nil, errors.Wrap(err, "while extracting name/field in dotpath case []interface{}")
}
return elems, nil
} else {
// No inner indexing
for _, elem := range data {
logger.Debug(" - elem", "elem", elem, "paths", paths, "P", P)
switch V := elem.(type) {
case map[string]interface{}:
logger.Debug(" map[string]")
val, err := get_from_smap_by_path(IDX, paths, V)
if err != nil {
logger.Debug("could not find '" + P + "' in object")
continue
}
logger.Debug("Adding val", "val", val)
subs = append(subs, val)
case map[interface{}]interface{}:
logger.Debug(" map[iface]")
val, err := get_from_imap_by_path(IDX, paths, V)
if err != nil {
logger.Debug("could not find '" + P + "' in object")
continue
}
logger.Debug("Adding val", "val", val)
subs = append(subs, val)
default:
str := fmt.Sprintf("%+v", reflect.TypeOf(V))
return nil, errors.New("element not an object type: " + str)
}
}
}
if len(subs) == 1 {
return subs[0], nil
}
return subs, nil
}