summaryrefslogtreecommitdiff
path: root/vendor/github.com/exponent-io/jsonpath/pathaction.go
blob: 497ed686ca9a502f89171a3eb07f5d545a271b39 (plain)
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
package jsonpath

// pathNode is used to construct a trie of paths to be matched
type pathNode struct {
	matchOn    interface{} // string, or integer
	childNodes []pathNode
	action     DecodeAction
}

// match climbs the trie to find a node that matches the given JSON path.
func (n *pathNode) match(path JsonPath) *pathNode {
	var node *pathNode = n
	for _, ps := range path {
		found := false
		for i, n := range node.childNodes {
			if n.matchOn == ps {
				node = &node.childNodes[i]
				found = true
				break
			} else if _, ok := ps.(int); ok && n.matchOn == AnyIndex {
				node = &node.childNodes[i]
				found = true
				break
			}
		}
		if !found {
			return nil
		}
	}
	return node
}

// PathActions represents a collection of DecodeAction functions that should be called at certain path positions
// when scanning the JSON stream. PathActions can be created once and used many times in one or more JSON streams.
type PathActions struct {
	node pathNode
}

// DecodeAction handlers are called by the Decoder when scanning objects. See PathActions.Add for more detail.
type DecodeAction func(d *Decoder) error

// Add specifies an action to call on the Decoder when the specified path is encountered.
func (je *PathActions) Add(action DecodeAction, path ...interface{}) {

	var node *pathNode = &je.node
	for _, ps := range path {
		found := false
		for i, n := range node.childNodes {
			if n.matchOn == ps {
				node = &node.childNodes[i]
				found = true
				break
			}
		}
		if !found {
			node.childNodes = append(node.childNodes, pathNode{matchOn: ps})
			node = &node.childNodes[len(node.childNodes)-1]
		}
	}
	node.action = action
}