jmespath.cpp
C++ implementation of JMESPath, a query language for JSON http://jmespath.org
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
interpreter.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Author: Róbert Márki <gsmiko@gmail.com>
4 ** Copyright (c) 2016 Róbert Márki
5 **
6 ** This file is part of the jmespath.cpp project which is distributed under
7 ** the MIT License (MIT).
8 **
9 ** Permission is hereby granted, free of charge, to any person obtaining a copy
10 ** of this software and associated documentation files (the "Software"), to
11 ** deal in the Software without restriction, including without limitation the
12 ** rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13 ** sell copies of the Software, and to permit persons to whom the Software is
14 ** furnished to do so, subject to the following conditions:
15 **
16 ** The above copyright notice and this permission notice shall be included in
17 ** all copies or substantial portions of the Software.
18 **
19 ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 ** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 ** DEALINGS IN THE SOFTWARE.
26 **
27 ****************************************************************************/
28 #ifndef INTERPRETER_H
29 #define INTERPRETER_H
31 #include "jmespath/types.h"
32 #include "src/ast/expressionnode.h"
34 #include <functional>
35 #include <tuple>
36 #include <unordered_map>
37 #include <boost/variant.hpp>
38 
39 namespace jmespath { namespace ast {
40 
41 class BinaryExpressionNode;
42 }} // namespace jmespath::ast
43 
44 namespace jmespath { namespace interpreter {
45 
49 using JsonRef = std::reference_wrapper<const Json>;
55 using ContextValue = boost::variant<Json, JsonRef>;
56 
63 inline Json&& assignContextValue(Json&& value)
64 {
65  return std::move(value);
66 }
73 inline JsonRef assignContextValue(const Json& value)
74 {
75  return std::cref(value);
76 }
77 
83 inline const Json& getJsonValue(const ContextValue& contextValue)
84 {
85  return boost::apply_visitor([](const auto& value) -> const Json& {
86  return value;
87  }, contextValue);
88 }
89 
96 {
97 public:
101  Interpreter();
106  template <typename JsonT>
107  std::enable_if_t<std::is_same<std::decay_t<JsonT>, Json>::value, void>
108  setContext(JsonT&& value)
109  {
110  m_context = assignContextValue(std::forward<JsonT>(value));
111  }
116  const Json &currentContext() const
117  {
118  return getJsonValue(m_context);
119  }
126  {
127  return m_context;
128  }
134  virtual void evaluateProjection(const ast::ExpressionNode* expression);
135 
141  void visit(const ast::AbstractNode *node) override;
142  void visit(const ast::ExpressionNode *node) override;
143  void visit(const ast::IdentifierNode *node) override;
144  void visit(const ast::RawStringNode *node) override;
145  void visit(const ast::LiteralNode* node) override;
146  void visit(const ast::SubexpressionNode* node) override;
147  void visit(const ast::IndexExpressionNode* node) override;
148  void visit(const ast::ArrayItemNode* node) override;
149  void visit(const ast::FlattenOperatorNode*) override;
150  void visit(const ast::BracketSpecifierNode* node) override;
151  void visit(const ast::SliceExpressionNode* node) override;
152  void visit(const ast::ListWildcardNode*) override;
153  void visit(const ast::HashWildcardNode* node) override;
154  void visit(const ast::MultiselectListNode* node) override;
155  void visit(const ast::MultiselectHashNode* node) override;
156  void visit(const ast::NotExpressionNode* node) override;
157  void visit(const ast::ComparatorExpressionNode* node) override;
158  void visit(const ast::OrExpressionNode* node) override;
159  void visit(const ast::AndExpressionNode* node) override;
160  void visit(const ast::ParenExpressionNode* node) override;
161  void visit(const ast::PipeExpressionNode* node) override;
162  void visit(const ast::CurrentNode*) override;
163  void visit(const ast::FilterExpressionNode* node) override;
164  void visit(const ast::FunctionExpressionNode* node) override;
165  void visit(const ast::ExpressionArgumentNode*) override;
168 private:
172  using FunctionArgument
173  = boost::variant<boost::blank, ContextValue, ast::ExpressionNode>;
177  using FunctionArgumentList = std::vector<FunctionArgument>;
182  using Function = std::function<void(FunctionArgumentList&)>;
187  using JsonComparator = std::function<bool(const Json&, const Json&)>;
191  using ArgumentArityValidator = std::function<bool(const size_t&)>;
200  using FunctionDescriptor = std::tuple<ArgumentArityValidator,
201  bool,
207  = std::vector<ast::FunctionExpressionNode::ArgumentType>;
216  std::unordered_map<String, FunctionDescriptor> m_functionMap;
225  template <typename JsonT>
226  void visit(const ast::IdentifierNode *node, JsonT&& context);
227  template <typename JsonT>
228  void visit(const ast::ArrayItemNode *node, JsonT&& context);
229  template <typename JsonT>
230  void visit(const ast::FlattenOperatorNode* node, JsonT&& context);
231  template <typename JsonT>
232  void visit(const ast::SliceExpressionNode* node, JsonT&& context);
233  template <typename JsonT>
234  void visit(const ast::HashWildcardNode* node, JsonT&& context);
235  template <typename JsonT>
236  void visit(const ast::FilterExpressionNode* node, JsonT&& context);
247  Index endpoint,
248  Index step) const;
255  bool toBoolean(const Json& json) const;
264  template <typename JsonT>
265  void evaluateProjection(const ast::ExpressionNode* expression,
266  JsonT&& context);
277  bool shortCircuitValue);
290  const FunctionExpressionArgumentList& arguments,
291  const std::shared_ptr<ContextValue> &contextValue);
299  template <typename T>
300  T& getArgument(FunctionArgument& argument) const;
307  const Json& getJsonArgument(FunctionArgument& argument) const;
314  void abs(FunctionArgumentList& arguments);
322  void avg(FunctionArgumentList& arguments);
330  void contains(FunctionArgumentList& arguments);
337  void ceil(FunctionArgumentList& arguments);
345  void endsWith(FunctionArgumentList& arguments);
352  void floor(FunctionArgumentList& arguments);
360  void join(FunctionArgumentList& arguments);
367  void keys(FunctionArgumentList& arguments);
374  void length(FunctionArgumentList& arguments);
382  void map(FunctionArgumentList& arguments);
392  template <typename JsonT>
393  void map(const ast::ExpressionNode* node, JsonT&& array);
401  void merge(FunctionArgumentList& arguments);
410  template <typename JsonT>
411  void mergeObject(Json* object, JsonT&& sourceObject);
418  void notNull(FunctionArgumentList& arguments);
425  void reverse(FunctionArgumentList& arguments);
432  void reverse(Json&& subject);
439  void sort(FunctionArgumentList& arguments);
446  void sort(Json&& array);
454  void sortBy(FunctionArgumentList& arguments);
463  void sortBy(const ast::ExpressionNode* expression, Json&& array);
471  void startsWith(FunctionArgumentList& arguments);
478  void sum(FunctionArgumentList& arguments);
485  void toArray(FunctionArgumentList& arguments);
492  template <typename JsonT>
493  void toArray(JsonT&& value);
500  void toString(FunctionArgumentList& arguments);
507  template <typename JsonT>
508  void toString(JsonT&& value);
516  void toNumber(FunctionArgumentList& arguments);
523  template <typename JsonT>
524  void toNumber(JsonT&& value);
531  void type(FunctionArgumentList& arguments);
538  void values(FunctionArgumentList& arguments);
545  template <typename JsonT>
546  void values(JsonT&& object);
557  void max(FunctionArgumentList& arguments, const JsonComparator& comparator);
568  template <typename JsonT>
569  void max(const JsonComparator* comparator, JsonT&& array);
581  void maxBy(FunctionArgumentList& arguments,
582  const JsonComparator& comparator = std::less<Json>{});
596  template <typename JsonT>
597  void maxBy(const ast::ExpressionNode* expression,
598  const JsonComparator* comparator,
599  JsonT&& array);
607  bool isComparableArray(const Json& array) const;
608 };
609 }} // namespace jmespath::interpreter
610 #endif // INTERPRETER_H
void floor(FunctionArgumentList &arguments)
Rounds down the first item of the given arguments to the next lowest integer value. The first item should be a Json number.
Definition: interpreter.cpp:1031
boost::variant< Json, JsonRef > ContextValue
Evaluation context type.
Definition: interpreter.h:55
The ComparatorExpressionNode class represents a JMESPath comparator expression.
Definition: comparatorexpressionnode.h:39
The ListWildcardNode class represents a JMESPath list wildcard expression.
Definition: listwildcardnode.h:38
Json && assignContextValue(Json &&value)
Convert the given value to something assignable to a ContextValue variable.
Definition: interpreter.h:63
std::function< bool(const size_t &)> ArgumentArityValidator
Function argument arity validator predicate.
Definition: interpreter.h:191
std::function< void(FunctionArgumentList &)> Function
Function wrapper type to which JMESPath built in function implementations should conform to...
Definition: interpreter.h:182
bool isComparableArray(const Json &array) const
Checks whether array is a homogeneous array which contains comparable types like strings and numbers...
Definition: interpreter.cpp:1712
const Json & getJsonArgument(FunctionArgument &argument) const
Creates a reference to the Json value held by the argument.
Definition: interpreter.cpp:888
void keys(FunctionArgumentList &arguments)
Extracts the keys from the object provided as the first item of the given arguments.
Definition: interpreter.cpp:1075
The HashWildcardNode class represents a JMESPath hash wildcard expression.
Definition: hashwildcardnode.h:38
void ceil(FunctionArgumentList &arguments)
Rounds up the first item of the given arguments to the next highest integer value. The first item should be a Json number.
Definition: interpreter.cpp:993
The CurrentNode class represents a JMESPath current node expression.
Definition: currentnode.h:38
The BracketSpecifierNode class represents a JMESPath bracket specifier.
Definition: bracketspecifiernode.h:44
ContextValue m_context
Stores the evaluation context.
Definition: interpreter.h:211
std::function< bool(const Json &, const Json &)> JsonComparator
The type of comparator functions used for comparing Json values.
Definition: interpreter.h:187
The IdentifierNode class represents a JMESPath identifier.
Definition: identifiernode.h:39
bool toBoolean(const Json &json) const
Converts the json value to a boolean.
Definition: interpreter.cpp:822
void sort(FunctionArgumentList &arguments)
Sorts the first item in the given arguments, which must either be an array of numbers or an array of ...
Definition: interpreter.cpp:1278
The AndExpressionNode class represents a JMESPath and expression.
Definition: andexpressionnode.h:38
void join(FunctionArgumentList &arguments)
Joins every item in the array provided as the second item of the given arguments with the first item ...
Definition: interpreter.cpp:1052
std::enable_if_t< std::is_same< std::decay_t< JsonT >, Json >::value, void > setContext(JsonT &&value)
Sets the context of the evaluation.
Definition: interpreter.h:108
The SliceExpressionNode class represents a JMESPath slice expression.
Definition: sliceexpressionnode.h:41
std::tuple< ArgumentArityValidator, bool, Function > FunctionDescriptor
Describes a built in function implementation.
Definition: interpreter.h:202
void notNull(FunctionArgumentList &arguments)
Accepts one or more items in arguments, and will evaluate them in order until a non null argument is ...
Definition: interpreter.cpp:1224
The MultiselectHashNode class represents a JMESPath multiselect hash expression.
Definition: multiselecthashnode.h:45
void length(FunctionArgumentList &arguments)
Returns the length of the first item in the given arguments. The first item must be either an array a...
Definition: interpreter.cpp:1094
The PipeExpressionNode class represents a JMESPath pipe expression.
Definition: pipeexpressionnode.h:38
void maxBy(FunctionArgumentList &arguments, const JsonComparator &comparator=std::less< Json >{})
Finds the largest item in the array provided as the first item in the arguments, which must either be...
Definition: interpreter.cpp:1637
nlohmann::json Json
JSON data type.
Definition: types.h:66
void toNumber(FunctionArgumentList &arguments)
Converts the string provided as the first item in the given arguments to a number. If it's already a number then the original value is returned, all other Json types are converted to null.
Definition: interpreter.cpp:1498
void startsWith(FunctionArgumentList &arguments)
Checks wheather the string provided as the first item in arguments starts with the string provided as...
Definition: interpreter.cpp:1381
const Json & currentContext() const
Returns the current evaluation context.
Definition: interpreter.h:116
The BinaryExpressionNode class is the base class for all node types which consist of a left and a rig...
Definition: binaryexpressionnode.h:39
The SubexpressionNode class represents a JMESPath subexpression.
Definition: subexpressionnode.h:37
The ExpressionArgumentNode class represents a JMESPath expression argument.
Definition: expressionargumentnode.h:40
Interpreter()
Constructs an Interpreter object.
Definition: interpreter.cpp:46
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< std::numeric_limits< size_t >::digits, std::numeric_limits< size_t >::digits, boost::multiprecision::signed_magnitude, boost::multiprecision::checked, void > > Index
Signed integer type that can hold all values in the range of numeric_limits<size_t>::max() * -1 ...
Definition: types.h:77
const Json & getJsonValue(const ContextValue &contextValue)
Extract the Json value held by the given value.
Definition: interpreter.h:83
void map(FunctionArgumentList &arguments)
Applies the expression provided as the first item in the given arguments to every item in the array p...
Definition: interpreter.cpp:1122
void evaluateLogicOperator(const ast::BinaryExpressionNode *node, bool shortCircuitValue)
Evaluates a binary logic operator to the result of the left side expression if it's binary value equa...
Definition: interpreter.cpp:654
void sortBy(FunctionArgumentList &arguments)
Sorts the first item in the given arguments, which must either be an array of numbers or an array of ...
Definition: interpreter.cpp:1307
void merge(FunctionArgumentList &arguments)
Accepts zero or more objects in the given arguments, and returns a single object with subsequent obje...
Definition: interpreter.cpp:1173
void visit(const ast::AbstractNode *node) override
Evaluate the given node on the current context value.
Definition: interpreter.cpp:189
boost::variant< boost::blank, ContextValue, ast::ExpressionNode > FunctionArgument
Type of the arguments in FunctionArgumentList.
Definition: interpreter.h:173
void mergeObject(Json *object, JsonT &&sourceObject)
Merges the items of the sourceObject into object.
Definition: interpreter.cpp:1214
void values(FunctionArgumentList &arguments)
Extracts the values from the object provided as the first item of the given arguments.
Definition: interpreter.cpp:1566
std::reference_wrapper< const Json > JsonRef
Copyable and assignable reference to a constant Json value.
Definition: interpreter.h:49
FunctionArgumentList evaluateArguments(const FunctionExpressionArgumentList &arguments, const std::shared_ptr< ContextValue > &contextValue)
Evaluate the given function expression arguments.
Definition: interpreter.cpp:832
The LiteralNode class represents a JMESPath literal string.
Definition: literalnode.h:39
The FilterExpressionNode class represents a JMESPath filter expression.
Definition: filterexpressionnode.h:39
std::unordered_map< String, FunctionDescriptor > m_functionMap
Maps the JMESPath built in function names to their implementations.
Definition: interpreter.h:216
The OrExpressionNode class represents a JMESPath or expression.
Definition: orexpressionnode.h:38
The AbstractVisitor class is an interface which defines the member functions required to visit every ...
Definition: abstractvisitor.h:71
void avg(FunctionArgumentList &arguments)
Calculates the average value of the items in the first item of the given arguments. The first item must be an Json array and every item in the array must be a number Json value.
Definition: interpreter.cpp:913
The IndexExpressionNode class represents a JMESPath index expression.
Definition: indexexpressionnode.h:39
void reverse(FunctionArgumentList &arguments)
Reverses the order of the first item in arguments. It must either be an array or a string...
Definition: interpreter.cpp:1242
void abs(FunctionArgumentList &arguments)
Calculates the absolute value of the first item in the given list of arguments. The first item must b...
Definition: interpreter.cpp:893
virtual void evaluateProjection(const ast::ExpressionNode *expression)
Evaluates the projection of the given expression on the current context.
Definition: interpreter.cpp:126
The NotExpressionNode class represents a JMESPath not expression.
Definition: notexpressionnode.h:39
The RawStringNode class represents a JMESPath raw string literal.
Definition: rawstringnode.h:39
void type(FunctionArgumentList &arguments)
Returns the type of the Json value provided as the first item in arguments.
Definition: interpreter.cpp:1541
void contains(FunctionArgumentList &arguments)
Checks whether the first item in the given arguments contains the second item. The first item should ...
Definition: interpreter.cpp:961
The ArrayItemNode class represents a JMESPath array index expression.
Definition: arrayitemnode.h:40
void toString(FunctionArgumentList &arguments)
Converts the first item of the given arguments to the Json encoded value if it's not already a string...
Definition: interpreter.cpp:1468
void endsWith(FunctionArgumentList &arguments)
Checks whether the first item of the given arguments ends with the second item. The first and second ...
Definition: interpreter.cpp:1014
The FlattenOperatorNode class represents a JMESPath flatten operator.
Definition: flattenoperatornode.h:39
Index adjustSliceEndpoint(size_t length, Index endpoint, Index step) const
Adjust the value of the slice endpoint to make sure it's within the array's bounds and points to the ...
Definition: interpreter.cpp:803
The MultiselectListNode class represents a JMESPath list wildcard expression.
Definition: multiselectlistnode.h:42
The ExpressionNode class represents a JMESPath expression.
Definition: expressionnode.h:56
std::vector< ast::FunctionExpressionNode::ArgumentType > FunctionExpressionArgumentList
List of unevaluated function arguments.
Definition: interpreter.h:207
void toArray(FunctionArgumentList &arguments)
Converts the first item of the given arguments to a one element array if it's not already an array...
Definition: interpreter.cpp:1435
std::vector< FunctionArgument > FunctionArgumentList
List of FunctionArgument objects.
Definition: interpreter.h:177
T & getArgument(FunctionArgument &argument) const
Converts the given function argument to the requsted type.
Definition: interpreter.cpp:874
void sum(FunctionArgumentList &arguments)
Calculates the sum of the numbers in the array provided as the first item of arguments.
Definition: interpreter.cpp:1398
void max(FunctionArgumentList &arguments, const JsonComparator &comparator)
Finds the largest item in the array provided as the first item in the arguments, it must either be an...
Definition: interpreter.cpp:1596
The Interpreter class evaluates the AST structure on a Json context.
Definition: interpreter.h:95
ContextValue & currentContextValue()
Returns the current evaluation context which can either hold a value or a const reference.
Definition: interpreter.h:125
The ParenExpressionNode class represents a JMESPath paren expression.
Definition: parenexpressionnode.h:38
The AbstractNode class is the common interface class for all AST node types.
Definition: abstractnode.h:45
The FunctionExpressionNode class represents a JMESPath function expression.
Definition: functionexpressionnode.h:45