HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
variableExpression.h
Go to the documentation of this file.
1 //
2 // Copyright 2023 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_USD_SDF_VARIABLE_EXPRESSION
25 #define PXR_USD_SDF_VARIABLE_EXPRESSION
26 
27 /// \file sdf/variableExpression.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/sdf/api.h"
31 
32 #include "pxr/base/vt/dictionary.h"
33 #include "pxr/base/vt/value.h"
34 
35 #include <memory>
36 #include <string>
37 #include <unordered_set>
38 #include <vector>
39 
41 
42 namespace Sdf_VariableExpressionImpl {
43  class Node;
44 }
45 
46 /// \class SdfVariableExpression
47 ///
48 /// Class responsible for parsing and evaluating variable expressions.
49 ///
50 /// Variable expressions are written in a custom language and
51 /// represented in scene description as a string surrounded by backticks (`).
52 /// These expressions may refer to "expression variables", which are key-value
53 /// pairs authored as layer metadata. For example, when evaluating an
54 /// expression like:
55 ///
56 /// \code
57 /// `"a_${NAME}_string"`
58 /// \endcode
59 ///
60 /// The "${NAME}" portion of the string with the value of expression variable
61 /// "NAME".
62 ///
63 /// Higher levels of the system (e.g., composition) are responsible for
64 /// examining fields that support variable expressions, evaluating them
65 /// with the appropriate variables (via this class) and consuming the
66 /// results.
67 ///
68 /// See \ref Sdf_Page_VariableExpressions "Variable Expressions"
69 /// or more information on the expression language and areas of the system
70 /// where expressions may be used.
72 {
73 public:
74  /// Construct using the expression \p expr. If the expression cannot be
75  /// parsed, this object represents an invalid expression. Parsing errors
76  /// will be accessible via GetErrors.
77  SDF_API
78  explicit SdfVariableExpression(const std::string& expr);
79 
80  /// Construct an object representing an invalid expression.
81  SDF_API
83 
84  SDF_API
86 
87  /// Returns true if \p s is a variable expression, false otherwise.
88  /// A variable expression is a string surrounded by backticks (`).
89  ///
90  /// A return value of true does not guarantee that \p s is a valid
91  /// expression. This function is meant to be used as an initial check
92  /// to determine if a string should be considered as an expression.
93  SDF_API
94  static bool IsExpression(const std::string& s);
95 
96  /// Returns true if \p value holds a type that is supported by
97  /// variable expressions, false otherwise. If this function returns
98  /// true, \p value may be authored into the expression variables
99  /// dictionary.
100  SDF_API
101  static bool IsValidVariableType(const VtValue& value);
102 
103  /// Returns true if this object represents a valid expression, false
104  /// if it represents an invalid expression.
105  ///
106  /// A return value of true does not mean that evaluation of this
107  /// expression is guaranteed to succeed. For example, an expression may
108  /// refer to a variable whose value is an invalid expression.
109  /// Errors like this can only be discovered by calling Evaluate.
110  SDF_API
111  explicit operator bool() const;
112 
113  /// Returns the expression string used to construct this object.
114  SDF_API
115  const std::string& GetString() const;
116 
117  /// Returns a list of errors encountered when parsing this expression.
118  ///
119  /// If the expression was parsed successfully, this list will be empty.
120  /// However, additional errors may be encountered when evaluating the e
121  /// expression.
122  SDF_API
123  const std::vector<std::string>& GetErrors() const;
124 
125  /// \class Result
126  class Result
127  {
128  public:
129  /// The result of evaluating the expression. This value may be
130  /// empty if the expression yielded no value. It may also be empty
131  /// if errors occurred during evaluation. In this case, the errors
132  /// field will be populated with error messages.
134 
135  /// Errors encountered while evaluating the expression.
136  std::vector<std::string> errors;
137 
138  /// Set of variables that were used while evaluating
139  /// the expression. For example, for an expression like
140  /// `"example_${VAR}_expression"`, this set will contain "VAR".
141  ///
142  /// This set will also contain variables from subexpressions.
143  /// In the above example, if the value of "VAR" was another
144  /// expression like `"sub_${SUBVAR}_expression"`, this set will
145  /// contain both "VAR" and "SUBVAR".
146  std::unordered_set<std::string> usedVariables;
147  };
148 
149  /// Evaluates this expression using the variables in
150  /// \p variables and returns a Result object with the final
151  /// value. If an error occurs during evaluation, the value field
152  /// in the Result object will be an empty VtValue and error messages
153  /// will be added to the errors field.
154  ///
155  /// If this object represents an invalid expression, calling this
156  /// function will return a Result object with an empty value and the
157  /// errors from GetErrors().
158  ///
159  /// If any values in \p variables used by this expression
160  /// are themselves expressions, they will be parsed and evaluated.
161  /// If an error occurs while evaluating any of these subexpressions,
162  /// evaluation of this expression fails and the encountered errors
163  /// will be added in the Result's list of errors.
164  SDF_API
165  Result Evaluate(const VtDictionary& variables) const;
166 
167  /// Evaluates this expression using the variables in
168  /// \p variables and returns a Result object with the final
169  /// value.
170  ///
171  /// This is a convenience function that calls Evaluate and ensures that
172  /// the value in the Result object is either an empty VtValue or is
173  /// holding the specified ResultType. If this is not the case, the
174  /// Result value will be set to an empty VtValue an error message
175  /// indicating the unexpected type will be added to the Result's error
176  /// list. Otherwise, the Result will be returned as-is.
177  template <class ResultType>
178  Result EvaluateTyped(const VtDictionary& variables) const
179  {
180  Result r = Evaluate(variables);
181  if (!r.value.IsEmpty() && !r.value.IsHolding<ResultType>()) {
182  r.errors.push_back(
183  _FormatUnexpectedTypeError(r.value, VtValue(ResultType())));
184  r.value = VtValue();
185  }
186  return r;
187  }
188 
189 private:
190  SDF_API
191  static std::string
192  _FormatUnexpectedTypeError(const VtValue& got, const VtValue& expected);
193 
194  std::vector<std::string> _errors;
195  std::shared_ptr<Sdf_VariableExpressionImpl::Node> _expression;
196  std::string _expressionStr;
197 };
198 
200 
201 #endif
SDF_API SdfVariableExpression()
Construct an object representing an invalid expression.
SDF_API Result Evaluate(const VtDictionary &variables) const
Definition: Node.h:52
std::unordered_set< std::string > usedVariables
SDF_API ~SdfVariableExpression()
static SDF_API bool IsExpression(const std::string &s)
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
GLdouble s
Definition: glad.h:3009
bool IsEmpty() const
Returns true iff this value is empty.
Definition: value.h:1272
SDF_API const std::vector< std::string > & GetErrors() const
static SDF_API bool IsValidVariableType(const VtValue &value)
#define SDF_API
Definition: api.h:40
std::vector< std::string > errors
Errors encountered while evaluating the expression.
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
bool IsHolding() const
Definition: value.h:1054
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
Definition: core.h:1131
GLboolean r
Definition: glcorearb.h:1222
SDF_API const std::string & GetString() const
Returns the expression string used to construct this object.
Definition: value.h:167
Result EvaluateTyped(const VtDictionary &variables) const