1 // Package query performs JSONPath-like queries on a TOML document.
3 // The query path implementation is based loosely on the JSONPath specification:
4 // http://goessner.net/articles/JsonPath/.
6 // The idea behind a query path is to allow quick access to any element, or set
7 // of elements within TOML document, with a single expression.
9 // result, err := query.CompileAndExecute("$.foo.bar.baz", tree)
11 // This is roughly equivalent to:
13 // next := tree.Get("foo")
15 // next = next.Get("bar")
17 // next = next.Get("baz")
22 // err is nil if any parsing exception occurs.
24 // If no node in the tree matches the query, result will simply contain an empty list of
27 // As illustrated above, the query path is much more efficient, especially since
28 // the structure of the TOML file can vary. Rather than making assumptions about
29 // a document's structure, a query allows the programmer to make structured
30 // requests into the document, and get zero or more values as a result.
34 // The syntax of a query begins with a root token, followed by any number
38 // Root of the TOML tree. This must always come first.
40 // Selects child of this node, where 'name' is a TOML key
43 // Selects child of this node, where 'name' is a string
44 // containing a TOML key name.
46 // Selcts child array element at 'index'.
48 // Recursively selects all children, filtered by an a union,
49 // index, or slice expression.
51 // Recursive selection of all nodes at this point in the
54 // Selects all children of the current node.
56 // Union operator - a logical 'or' grouping of two or more
57 // sub-expressions: index, key name, or filter.
59 // Slice operator - selects array elements from start to
60 // end-1, at the given step. All three arguments are
63 // Named filter expression - the function 'filter' is
64 // used to filter children at this node.
66 // Query Indexes And Slices
68 // Index expressions perform no bounds checking, and will contribute no
69 // values to the result set if the provided index or index range is invalid.
70 // Negative indexes represent values from the end of the array, counting backwards.
72 // // select the last index of the array named 'foo'
73 // query.CompileAndExecute("$.foo[-1]", tree)
75 // Slice expressions are supported, by using ':' to separate a start/end index pair.
77 // // select up to the first five elements in the array
78 // query.CompileAndExecute("$.foo[0:5]", tree)
80 // Slice expressions also allow negative indexes for the start and stop
83 // // select all array elements.
84 // query.CompileAndExecute("$.foo[0:-1]", tree)
86 // Slice expressions may have an optional stride/step parameter:
88 // // select every other element
89 // query.CompileAndExecute("$.foo[0:-1:2]", tree)
91 // Slice start and end parameters are also optional:
93 // // these are all equivalent and select all the values in the array
94 // query.CompileAndExecute("$.foo[:]", tree)
95 // query.CompileAndExecute("$.foo[0:]", tree)
96 // query.CompileAndExecute("$.foo[:-1]", tree)
97 // query.CompileAndExecute("$.foo[0:-1:]", tree)
98 // query.CompileAndExecute("$.foo[::1]", tree)
99 // query.CompileAndExecute("$.foo[0::1]", tree)
100 // query.CompileAndExecute("$.foo[:-1:1]", tree)
101 // query.CompileAndExecute("$.foo[0:-1:1]", tree)
105 // Query filters are used within a Union [,] or single Filter [] expression.
106 // A filter only allows nodes that qualify through to the next expression,
107 // and/or into the result set.
109 // // returns children of foo that are permitted by the 'bar' filter.
110 // query.CompileAndExecute("$.foo[?(bar)]", tree)
112 // There are several filters provided with the library:
115 // Allows nodes of type Tree.
117 // Allows nodes of type int64.
119 // Allows nodes of type float64.
121 // Allows nodes of type string.
123 // Allows nodes of type time.Time.
125 // Allows nodes of type bool.
129 // An executed query returns a Result object. This contains the nodes
130 // in the TOML tree that qualify the query expression. Position information
131 // is also available for each value in the set.
133 // // display the results of a query
134 // results := query.CompileAndExecute("$.foo.bar.baz", tree)
135 // for idx, value := results.Values() {
136 // fmt.Println("%v: %v", results.Positions()[idx], value)
141 // Queries may be executed directly on a Tree object, or compiled ahead
142 // of time and executed discretely. The former is more convenient, but has the
143 // penalty of having to recompile the query expression each time.
146 // results := query.CompileAndExecute("$.foo.bar.baz", tree)
149 // query, err := toml.Compile("$.foo.bar.baz")
150 // results := query.Execute(tree)
152 // // run the compiled query again on a different tree
153 // moreResults := query.Execute(anotherTree)
155 // User Defined Query Filters
157 // Filter expressions may also be user defined by using the SetFilter()
158 // function on the Query object. The function must return true/false, which
159 // signifies if the passed node is kept or discarded, respectively.
161 // // create a query that references a user-defined filter
162 // query, _ := query.Compile("$[?(bazOnly)]")
164 // // define the filter, and assign it to the query
165 // query.SetFilter("bazOnly", func(node interface{}) bool{
166 // if tree, ok := node.(*Tree); ok {
167 // return tree.Has("baz")
169 // return false // reject all other node types
173 // query.Execute(tree)