5 "github.com/pelletier/go-toml"
9 type matchBase struct {
13 func (f *matchBase) setNext(next pathFn) {
17 // terminating functor - gathers results
18 type terminatingFn struct {
22 func newTerminatingFn() *terminatingFn {
23 return &terminatingFn{}
26 func (f *terminatingFn) setNext(next pathFn) {
30 func (f *terminatingFn) call(node interface{}, ctx *queryContext) {
31 ctx.result.appendResult(node, ctx.lastPosition)
35 type matchKeyFn struct {
40 func newMatchKeyFn(name string) *matchKeyFn {
41 return &matchKeyFn{Name: name}
44 func (f *matchKeyFn) call(node interface{}, ctx *queryContext) {
45 if array, ok := node.([]*toml.Tree); ok {
46 for _, tree := range array {
47 item := tree.Get(f.Name)
49 ctx.lastPosition = tree.GetPosition(f.Name)
50 f.next.call(item, ctx)
53 } else if tree, ok := node.(*toml.Tree); ok {
54 item := tree.Get(f.Name)
56 ctx.lastPosition = tree.GetPosition(f.Name)
57 f.next.call(item, ctx)
63 type matchIndexFn struct {
68 func newMatchIndexFn(idx int) *matchIndexFn {
69 return &matchIndexFn{Idx: idx}
72 func (f *matchIndexFn) call(node interface{}, ctx *queryContext) {
73 if arr, ok := node.([]interface{}); ok {
74 if f.Idx < len(arr) && f.Idx >= 0 {
75 if treesArray, ok := node.([]*toml.Tree); ok {
76 if len(treesArray) > 0 {
77 ctx.lastPosition = treesArray[0].Position()
80 f.next.call(arr[f.Idx], ctx)
86 type matchSliceFn struct {
91 func newMatchSliceFn(start, end, step int) *matchSliceFn {
92 return &matchSliceFn{Start: start, End: end, Step: step}
95 func (f *matchSliceFn) call(node interface{}, ctx *queryContext) {
96 if arr, ok := node.([]interface{}); ok {
97 // adjust indexes for negative values, reverse ordering
98 realStart, realEnd := f.Start, f.End
100 realStart = len(arr) + realStart
103 realEnd = len(arr) + realEnd
105 if realEnd < realStart {
106 realEnd, realStart = realStart, realEnd // swap
109 for idx := realStart; idx < realEnd; idx += f.Step {
110 if treesArray, ok := node.([]*toml.Tree); ok {
111 if len(treesArray) > 0 {
112 ctx.lastPosition = treesArray[0].Position()
115 f.next.call(arr[idx], ctx)
121 type matchAnyFn struct {
125 func newMatchAnyFn() *matchAnyFn {
129 func (f *matchAnyFn) call(node interface{}, ctx *queryContext) {
130 if tree, ok := node.(*toml.Tree); ok {
131 for _, k := range tree.Keys() {
133 ctx.lastPosition = tree.GetPosition(k)
139 // filter through union
140 type matchUnionFn struct {
144 func (f *matchUnionFn) setNext(next pathFn) {
145 for _, fn := range f.Union {
150 func (f *matchUnionFn) call(node interface{}, ctx *queryContext) {
151 for _, fn := range f.Union {
156 // match every single last node in the tree
157 type matchRecursiveFn struct {
161 func newMatchRecursiveFn() *matchRecursiveFn {
162 return &matchRecursiveFn{}
165 func (f *matchRecursiveFn) call(node interface{}, ctx *queryContext) {
166 originalPosition := ctx.lastPosition
167 if tree, ok := node.(*toml.Tree); ok {
168 var visit func(tree *toml.Tree)
169 visit = func(tree *toml.Tree) {
170 for _, k := range tree.Keys() {
172 ctx.lastPosition = tree.GetPosition(k)
174 switch node := v.(type) {
178 for _, subtree := range node {
184 ctx.lastPosition = originalPosition
185 f.next.call(tree, ctx)
190 // match based on an externally provided functional filter
191 type matchFilterFn struct {
197 func newMatchFilterFn(name string, pos toml.Position) *matchFilterFn {
198 return &matchFilterFn{Name: name, Pos: pos}
201 func (f *matchFilterFn) call(node interface{}, ctx *queryContext) {
202 fn, ok := (*ctx.filters)[f.Name]
204 panic(fmt.Sprintf("%s: query context does not have filter '%s'",
205 f.Pos.String(), f.Name))
207 switch castNode := node.(type) {
209 for _, k := range castNode.Keys() {
212 ctx.lastPosition = castNode.GetPosition(k)
217 for _, v := range castNode {
219 if len(castNode) > 0 {
220 ctx.lastPosition = castNode[0].Position()
226 for _, v := range castNode {