summaryrefslogtreecommitdiff
path: root/jsonpath/selector.go
diff options
context:
space:
mode:
Diffstat (limited to 'jsonpath/selector.go')
-rw-r--r--jsonpath/selector.go55
1 files changed, 55 insertions, 0 deletions
diff --git a/jsonpath/selector.go b/jsonpath/selector.go
new file mode 100644
index 0000000..71c3ed2
--- /dev/null
+++ b/jsonpath/selector.go
@@ -0,0 +1,55 @@
+package jsonpath
+
+import (
+ "src.userspace.com.au/query/json"
+)
+
+type Selector func(*json.Node) bool
+
+// MatchAll returns a slice of the nodes that match the selector,
+// from n and its children.
+func (s Selector) MatchAll(n *json.Node) []*json.Node {
+ return s.matchAllInto(n, nil)
+}
+
+func (s Selector) matchAllInto(n *json.Node, storage []*json.Node) []*json.Node {
+ if s(n) {
+ storage = append(storage, n)
+ }
+
+ for child := n.FirstChild; child != nil; child = child.NextSibling {
+ storage = s.matchAllInto(child, storage)
+ }
+
+ return storage
+}
+
+// Match returns true if the node matches the selector.
+func (s Selector) Match(n *json.Node) bool {
+ return s(n)
+}
+
+// MatchFirst returns the first node that matches s, from n and its children.
+func (s Selector) MatchFirst(n *json.Node) *json.Node {
+ if s.Match(n) {
+ return n
+ }
+
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ m := s.MatchFirst(c)
+ if m != nil {
+ return m
+ }
+ }
+ return nil
+}
+
+// Filter returns the nodes in nodes that match the selector.
+func (s Selector) Filter(nodes []*json.Node) (result []*json.Node) {
+ for _, n := range nodes {
+ if s(n) {
+ result = append(result, n)
+ }
+ }
+ return result
+}