OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / github.com / pelletier / go-toml / query / match.go
diff --git a/vendor/github.com/pelletier/go-toml/query/match.go b/vendor/github.com/pelletier/go-toml/query/match.go
new file mode 100644 (file)
index 0000000..d7bb15a
--- /dev/null
@@ -0,0 +1,232 @@
+package query
+
+import (
+       "fmt"
+       "github.com/pelletier/go-toml"
+)
+
+// base match
+type matchBase struct {
+       next pathFn
+}
+
+func (f *matchBase) setNext(next pathFn) {
+       f.next = next
+}
+
+// terminating functor - gathers results
+type terminatingFn struct {
+       // empty
+}
+
+func newTerminatingFn() *terminatingFn {
+       return &terminatingFn{}
+}
+
+func (f *terminatingFn) setNext(next pathFn) {
+       // do nothing
+}
+
+func (f *terminatingFn) call(node interface{}, ctx *queryContext) {
+       ctx.result.appendResult(node, ctx.lastPosition)
+}
+
+// match single key
+type matchKeyFn struct {
+       matchBase
+       Name string
+}
+
+func newMatchKeyFn(name string) *matchKeyFn {
+       return &matchKeyFn{Name: name}
+}
+
+func (f *matchKeyFn) call(node interface{}, ctx *queryContext) {
+       if array, ok := node.([]*toml.Tree); ok {
+               for _, tree := range array {
+                       item := tree.Get(f.Name)
+                       if item != nil {
+                               ctx.lastPosition = tree.GetPosition(f.Name)
+                               f.next.call(item, ctx)
+                       }
+               }
+       } else if tree, ok := node.(*toml.Tree); ok {
+               item := tree.Get(f.Name)
+               if item != nil {
+                       ctx.lastPosition = tree.GetPosition(f.Name)
+                       f.next.call(item, ctx)
+               }
+       }
+}
+
+// match single index
+type matchIndexFn struct {
+       matchBase
+       Idx int
+}
+
+func newMatchIndexFn(idx int) *matchIndexFn {
+       return &matchIndexFn{Idx: idx}
+}
+
+func (f *matchIndexFn) call(node interface{}, ctx *queryContext) {
+       if arr, ok := node.([]interface{}); ok {
+               if f.Idx < len(arr) && f.Idx >= 0 {
+                       if treesArray, ok := node.([]*toml.Tree); ok {
+                               if len(treesArray) > 0 {
+                                       ctx.lastPosition = treesArray[0].Position()
+                               }
+                       }
+                       f.next.call(arr[f.Idx], ctx)
+               }
+       }
+}
+
+// filter by slicing
+type matchSliceFn struct {
+       matchBase
+       Start, End, Step int
+}
+
+func newMatchSliceFn(start, end, step int) *matchSliceFn {
+       return &matchSliceFn{Start: start, End: end, Step: step}
+}
+
+func (f *matchSliceFn) call(node interface{}, ctx *queryContext) {
+       if arr, ok := node.([]interface{}); ok {
+               // adjust indexes for negative values, reverse ordering
+               realStart, realEnd := f.Start, f.End
+               if realStart < 0 {
+                       realStart = len(arr) + realStart
+               }
+               if realEnd < 0 {
+                       realEnd = len(arr) + realEnd
+               }
+               if realEnd < realStart {
+                       realEnd, realStart = realStart, realEnd // swap
+               }
+               // loop and gather
+               for idx := realStart; idx < realEnd; idx += f.Step {
+                       if treesArray, ok := node.([]*toml.Tree); ok {
+                               if len(treesArray) > 0 {
+                                       ctx.lastPosition = treesArray[0].Position()
+                               }
+                       }
+                       f.next.call(arr[idx], ctx)
+               }
+       }
+}
+
+// match anything
+type matchAnyFn struct {
+       matchBase
+}
+
+func newMatchAnyFn() *matchAnyFn {
+       return &matchAnyFn{}
+}
+
+func (f *matchAnyFn) call(node interface{}, ctx *queryContext) {
+       if tree, ok := node.(*toml.Tree); ok {
+               for _, k := range tree.Keys() {
+                       v := tree.Get(k)
+                       ctx.lastPosition = tree.GetPosition(k)
+                       f.next.call(v, ctx)
+               }
+       }
+}
+
+// filter through union
+type matchUnionFn struct {
+       Union []pathFn
+}
+
+func (f *matchUnionFn) setNext(next pathFn) {
+       for _, fn := range f.Union {
+               fn.setNext(next)
+       }
+}
+
+func (f *matchUnionFn) call(node interface{}, ctx *queryContext) {
+       for _, fn := range f.Union {
+               fn.call(node, ctx)
+       }
+}
+
+// match every single last node in the tree
+type matchRecursiveFn struct {
+       matchBase
+}
+
+func newMatchRecursiveFn() *matchRecursiveFn {
+       return &matchRecursiveFn{}
+}
+
+func (f *matchRecursiveFn) call(node interface{}, ctx *queryContext) {
+       originalPosition := ctx.lastPosition
+       if tree, ok := node.(*toml.Tree); ok {
+               var visit func(tree *toml.Tree)
+               visit = func(tree *toml.Tree) {
+                       for _, k := range tree.Keys() {
+                               v := tree.Get(k)
+                               ctx.lastPosition = tree.GetPosition(k)
+                               f.next.call(v, ctx)
+                               switch node := v.(type) {
+                               case *toml.Tree:
+                                       visit(node)
+                               case []*toml.Tree:
+                                       for _, subtree := range node {
+                                               visit(subtree)
+                                       }
+                               }
+                       }
+               }
+               ctx.lastPosition = originalPosition
+               f.next.call(tree, ctx)
+               visit(tree)
+       }
+}
+
+// match based on an externally provided functional filter
+type matchFilterFn struct {
+       matchBase
+       Pos  toml.Position
+       Name string
+}
+
+func newMatchFilterFn(name string, pos toml.Position) *matchFilterFn {
+       return &matchFilterFn{Name: name, Pos: pos}
+}
+
+func (f *matchFilterFn) call(node interface{}, ctx *queryContext) {
+       fn, ok := (*ctx.filters)[f.Name]
+       if !ok {
+               panic(fmt.Sprintf("%s: query context does not have filter '%s'",
+                       f.Pos.String(), f.Name))
+       }
+       switch castNode := node.(type) {
+       case *toml.Tree:
+               for _, k := range castNode.Keys() {
+                       v := castNode.Get(k)
+                       if fn(v) {
+                               ctx.lastPosition = castNode.GetPosition(k)
+                               f.next.call(v, ctx)
+                       }
+               }
+       case []*toml.Tree:
+               for _, v := range castNode {
+                       if fn(v) {
+                               if len(castNode) > 0 {
+                                       ctx.lastPosition = castNode[0].Position()
+                               }
+                               f.next.call(v, ctx)
+                       }
+               }
+       case []interface{}:
+               for _, v := range castNode {
+                       if fn(v) {
+                               f.next.call(v, ctx)
+                       }
+               }
+       }
+}