Loading...
Searching...
No Matches
variableExpression.h
Go to the documentation of this file.
1//
2// Copyright 2023 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_USD_SDF_VARIABLE_EXPRESSION
8#define PXR_USD_SDF_VARIABLE_EXPRESSION
9
11
12#include "pxr/pxr.h"
13#include "pxr/usd/sdf/api.h"
14
15#include "pxr/base/vt/array.h"
17#include "pxr/base/vt/value.h"
18
19#include <memory>
20#include <string>
21#include <unordered_set>
22#include <vector>
23
24PXR_NAMESPACE_OPEN_SCOPE
25
26namespace Sdf_VariableExpressionImpl {
27 class Node;
28}
29
64{
65public:
69 SDF_API
70 explicit SdfVariableExpression(const std::string& expr);
71
73 SDF_API
74 explicit SdfVariableExpression(std::string&& expr);
75
77 SDF_API
79
80 SDF_API
82
89 SDF_API
90 static bool IsExpression(const std::string& s);
91
99 SDF_API
100 static bool IsValidVariableType(const VtValue& value);
101
109 SDF_API
110 explicit operator bool() const;
111
113 SDF_API
114 const std::string& GetString() const;
115
121 SDF_API
122 const std::vector<std::string>& GetErrors() const;
123
126
129 class EmptyList { };
130
132 class Result
133 {
134 public:
142 VtValue value;
143
145 std::vector<std::string> errors;
146
155 std::unordered_set<std::string> usedVariables;
156 };
157
179 SDF_API
180 Result Evaluate(const VtDictionary& variables) const;
181
200 template <class ResultType>
201 Result EvaluateTyped(const VtDictionary& variables) const
202 {
203 Result r = Evaluate(variables);
204
205 if (VtIsArray<ResultType>::value && r.value.IsHolding<EmptyList>()) {
206 r.value = VtValue(ResultType());
207 }
208 else if (!r.value.IsEmpty() && !r.value.IsHolding<ResultType>()) {
209 r.errors.push_back(
210 _FormatUnexpectedTypeError(r.value, VtValue(ResultType())));
211 r.value = VtValue();
212 }
213 return r;
214 }
215
217
243
248 {
249 public:
250 SDF_API operator SdfVariableExpression() const;
251
252 private:
253 friend class SdfVariableExpression;
254 Builder(std::string&& expr) : _expr(std::move(expr)) { }
255 std::string _expr;
256 };
257
262 {
263 public:
266 template <class Argument>
267 FunctionBuilder& AddArgument(Argument&& arg);
268
269 SDF_API operator SdfVariableExpression() const;
270 SDF_API operator Builder() const &;
271 SDF_API operator Builder() &&;
272
273 private:
274 friend class SdfVariableExpression;
275 FunctionBuilder(const std::string& name) : _expr(name + '(') { }
276 std::string _expr;
277 };
278
283 {
284 public:
287 template <class Element>
288 ListBuilder& AddElement(Element&& elem);
289
292 template <class T>
293 ListBuilder& AddLiteralValues(const std::vector<T>& values);
294
295 SDF_API operator SdfVariableExpression() const;
296 SDF_API operator Builder() const &;
297 SDF_API operator Builder() &&;
298
299 private:
300 friend class SdfVariableExpression;
301 ListBuilder() : _expr("[") { }
302
303 std::string _expr;
304 };
305
311 template <class... Arguments>
312 static FunctionBuilder
313 MakeFunction(const std::string& fnName, Arguments&&... fnArgs)
314 {
315 FunctionBuilder b(fnName);
316 (b.AddArgument(std::forward<Arguments>(fnArgs)), ...);
317 return b;
318 }
319
325 template <class... Elements>
326 static ListBuilder
327 MakeList(Elements&&... elems)
328 {
329 ListBuilder b;
330 (b.AddElement(std::forward<Elements>(elems)), ...);
331 return b;
332 }
333
339 template <class T>
340 static ListBuilder
341 MakeListOfLiterals(const std::vector<T>& values)
342 {
343 return ListBuilder().AddLiteralValues(values);
344 }
345
347 SDF_API static Builder MakeLiteral(int64_t value);
348 SDF_API static Builder MakeLiteral(bool value);
349 SDF_API static Builder MakeLiteral(const std::string& value);
350 SDF_API static Builder MakeLiteral(const char* value);
351
353 SDF_API static Builder MakeNone();
354
357 SDF_API static Builder MakeVariable(const std::string& name);
358
360
361private:
362 SDF_API
363 static std::string
364 _FormatUnexpectedTypeError(const VtValue& got, const VtValue& expected);
365
366 SDF_API
367 static void
368 _AppendExpression(
369 std::string* expr, const SdfVariableExpression& arg, bool first);
370
371 SDF_API
372 static void
373 _AppendBuilder(std::string* expr, const Builder& b, bool first);
374
375 template <class Argument>
376 static void
377 _Append(std::string* expr, Argument&& arg, bool first)
378 {
379 // Avoid implicitly converting arg to an SdfVariableExpression
380 // since that would incur unnecessary parsing costs.
381 if constexpr (std::is_same_v<
382 std::decay_t<Argument>, SdfVariableExpression>) {
383 _AppendExpression(expr, std::forward<Argument>(arg), first);
384 }
385 else {
386 _AppendBuilder(expr, std::forward<Argument>(arg), first);
387 }
388 }
389
390 std::vector<std::string> _errors;
391 std::shared_ptr<Sdf_VariableExpressionImpl::Node> _expression;
392 std::string _expressionStr;
393};
394
395inline bool
396operator==(
399{
400 return true;
401}
402
403inline bool
404operator!=(
407{
408 return false;
409}
410
411template <class Argument>
414{
415 SdfVariableExpression::_Append(
416 &_expr, std::forward<Argument>(arg),
417 /* first = */ *_expr.rbegin() == '(');
418 return *this;
419}
420
421template <class Element>
424{
425 SdfVariableExpression::_Append(
426 &_expr, std::forward<Element>(arg),
427 /* first = */ *_expr.rbegin() == '[');
428 return *this;
429}
430
431template <class T>
434 const std::vector<T>& values)
435{
436 for (const T& v : values) {
438 }
439 return *this;
440}
441
442PXR_NAMESPACE_CLOSE_SCOPE
443
444#endif
Helper class for storing intermediate results when building a variable expression.
Helper class for storing intermediate results when building a function variable expression.
FunctionBuilder & AddArgument(Argument &&arg)
Add an expression as an argument to the function call.
Helper class for storing intermediate results when building a list variable expression.
ListBuilder & AddElement(Element &&elem)
Add an expression as an element to the list.
ListBuilder & AddLiteralValues(const std::vector< T > &values)
Add values in values as literal expressions to the list.
Class responsible for parsing and evaluating variable expressions.
SDF_API const std::string & GetString() const
Returns the expression string used to construct this object.
static SDF_API bool IsExpression(const std::string &s)
Returns true if s is a variable expression, false otherwise.
SDF_API SdfVariableExpression()
Construct an object representing an invalid expression.
static ListBuilder MakeListOfLiterals(const std::vector< T > &values)
Create a list expression with the values in values as literal elements.
static FunctionBuilder MakeFunction(const std::string &fnName, Arguments &&... fnArgs)
Create a function expression that calls the function named fnName with fnArgs as arguments,...
static SDF_API bool IsValidVariableType(const VtValue &value)
Returns true if value holds a type that is supported by variable expressions, false otherwise.
SDF_API SdfVariableExpression(std::string &&expr)
This is an overloaded member function, provided for convenience. It differs from the above function o...
SDF_API Result Evaluate(const VtDictionary &variables) const
Evaluates this expression using the variables in variables and returns a Result object with the final...
SDF_API const std::vector< std::string > & GetErrors() const
Returns a list of errors encountered when parsing this expression.
static SDF_API Builder MakeVariable(const std::string &name)
Create a variable reference expression for the variable named name, i.e.
static SDF_API Builder MakeNone()
Create a "None" literal expression.
static ListBuilder MakeList(Elements &&... elems)
Create a list expression with listElems as elements, i.e.
Result EvaluateTyped(const VtDictionary &variables) const
Evaluates this expression using the variables in variables and returns a Result object with the final...
static SDF_API Builder MakeLiteral(int64_t value)
Create a literal expression for value.
SDF_API SdfVariableExpression(const std::string &expr)
Construct using the expression expr.
A result value representing an empty list.
A map with string keys and VtValue values.
Definition: dictionary.h:52
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:90
STL namespace.
A trait to detect instantiations of VtArray, specialized in array.h.
Definition: traits.h:22