Loading...
Searching...
No Matches
pathExpressionEval.h
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_PATH_EXPRESSION_EVAL_H
8#define PXR_USD_SDF_PATH_EXPRESSION_EVAL_H
9
10#include "pxr/pxr.h"
11#include "pxr/usd/sdf/api.h"
12#include "pxr/usd/sdf/path.h"
13#include "pxr/usd/sdf/pathExpression.h"
14#include "pxr/usd/sdf/predicateExpression.h"
15#include "pxr/usd/sdf/predicateLibrary.h"
16#include "pxr/usd/sdf/predicateProgram.h"
17
18#include "pxr/base/arch/regex.h"
19#include "pxr/base/tf/functionRef.h"
20
21#include <string>
22#include <type_traits>
23#include <vector>
24
25PXR_NAMESPACE_OPEN_SCOPE
26
27// fwd decl
28template <class DomainType>
30
31// fwd decl
32template <class DomainType>
36
37// fwd decl
38class Sdf_PathExpressionEvalBase;
39
40// Helper base class for SdfPathExpressionEval. This factors out as much
41// template-parameter independent code as possible to reduce bloat & compile
42// times.
43class Sdf_PathExpressionEvalBase
44{
45public:
46 friend SDF_API bool
47 Sdf_MakePathExpressionEvalImpl(
48 Sdf_PathExpressionEvalBase &eval,
49 SdfPathExpression const &expr,
51 void (SdfPathExpression::PathPattern const &)> translatePattern);
52
55 bool IsEmpty() const {
56 return _ops.empty();
57 }
58
60 explicit operator bool() const {
61 return !IsEmpty();
62 }
63
64protected:
65 class _PatternImplBase;
66
67 class _PatternIncrSearchState {
68 friend class _PatternImplBase;
69 public:
70 void Pop(int newDepth) {
71 while (!_segmentMatchDepths.empty() &&
72 _segmentMatchDepths.back() >= newDepth) {
73 _segmentMatchDepths.pop_back();
74 }
75 if (newDepth <= _constantDepth) {
76 _constantDepth = -1;
77 }
78 }
79 private:
80 std::vector<int> _segmentMatchDepths;
81 int _constantDepth = -1; // 0 means constant at the _prefix level.
82 bool _constantValue = false;
83 };
84
85 class _PatternImplBase {
86 protected:
87 // This is not a constructor because the subclass wants to invoke this
88 // from its ctor, TfFunctionRef currently requires an lvalue, which is
89 // hard to conjure in a ctor initializer list.
90 SDF_API
91 void _Init(SdfPathExpression::PathPattern const &pattern,
93 int (SdfPredicateExpression const &)> linkPredicate);
94
95 SDF_API
97 _Match(
98 SdfPath const &path,
100 runNthPredicate) const;
101
102 SDF_API
104 _Next(_PatternIncrSearchState &searchState,
105 SdfPath const &path,
107 runNthPredicate) const;
108
109 enum _ComponentType {
110 ExplicitName, // an explicit name (not a glob pattern).
111 Regex // a glob pattern (handled via regex).
112 };
113
114 struct _Component {
115 _ComponentType type;
116 int patternIndex; // into either _explicitNames or _regexes
117 int predicateIndex; // into _predicates or -1 if no predicate.
118 };
119
120 struct _Segment {
121 // A _Segment is a half-open interval [begin, end) in _components.
122 bool IsEmpty() const { return begin == end; }
123 bool StartsAt(size_t idx) const { return begin == idx; }
124 bool EndsAt(size_t idx) const { return end == idx; }
125 size_t GetSize() const { return end - begin; }
126 size_t begin, end;
127 };
128
129 SdfPath _prefix;
130 std::vector<_Component> _components;
131 std::vector<_Segment> _segments;
132 std::vector<std::string> _explicitNames;
133 std::vector<ArchRegex> _regexes;
134
135 bool _stretchBegin;
136 bool _stretchEnd;
137 enum : uint8_t {
138 // The kind of objects this pattern is capable of matching.
139 _MatchPrimOrProp, _MatchPrimOnly, _MatchPropOnly
140 } _matchObjType;
141 };
142
143
144 // The passed \p invokePattern function must do two things: 1, if \p skip is
145 // false, test the current pattern for a match (otherwise skip it) and 2,
146 // advance to be ready to test the next pattern for a match on the next call
147 // to \p invokePattern.
148 SDF_API
150 _EvalExpr(TfFunctionRef<
151 SdfPredicateFunctionResult (bool /*skip*/)> invokePattern) const;
152
153 enum _Op { EvalPattern, Not, Open, Close, Or, And };
154
155 std::vector<_Op> _ops;
156};
157
166template <class DomainType>
167class SdfPathExpressionEval : public Sdf_PathExpressionEvalBase
168{
169 // This object implements matching against a single path pattern.
170 class _PatternImpl : public _PatternImplBase {
171 public:
172 _PatternImpl() = default;
173
174 _PatternImpl(SdfPathExpression::PathPattern const &pattern,
175 SdfPredicateLibrary<DomainType> const &predLib) {
176 auto linkPredicate =
177 [this, &predLib](SdfPredicateExpression const &predExpr) {
178 _predicates.push_back(
179 SdfLinkPredicateExpression(predExpr, predLib));
180 return _predicates.size()-1;
181 };
182 _Init(pattern, linkPredicate);
183 }
184
185 // Check objPath for a match against this pattern.
186 template <class PathToObject>
188 Match(SdfPath const &objPath,
189 PathToObject const &pathToObj) const {
190 auto runNthPredicate =
191 [this, &pathToObj](int i, SdfPath const &path) {
192 return _predicates[i](pathToObj(path));
193 };
194 return _Match(objPath, runNthPredicate);
195 }
196
197 // Perform the next incremental search step against this pattern.
198 template <class PathToObject>
200 Next(SdfPath const &objPath,
201 _PatternIncrSearchState &search,
202 PathToObject const &pathToObj) const {
203 auto runNthPredicate =
204 [this, &pathToObj](int i, SdfPath const &path) {
205 return _predicates[i](pathToObj(path));
206 };
207 return _Next(search, objPath, runNthPredicate);
208 }
209
210 private:
211 std::vector<SdfPredicateProgram<DomainType>> _predicates;
212 };
213
214public:
218 SdfMakePathExpressionEval<DomainType>(
219 SdfPathExpression const &expr,
221
222 bool IsEmpty() const {
223 return _patternImpls.empty();
224 }
225
227 template <class PathToObject>
229 Match(SdfPath const &objPath,
230 PathToObject const &pathToObj) const {
231 if (IsEmpty()) {
233 }
234 auto patternImplIter = _patternImpls.cbegin();
235 auto evalPattern = [&](bool skip) {
236 return skip ? (++patternImplIter, SdfPredicateFunctionResult()) :
237 (*patternImplIter++).Match(objPath, pathToObj);
238 };
239 return _EvalExpr(evalPattern);
240 }
241
249 template <class PathToObject>
251 public:
252 IncrementalSearcher() : _eval(nullptr), _lastPathDepth(0) {}
253
255 PathToObject const &p2o)
256 : _eval(eval)
257 , _incrSearchStates(_eval->_patternImpls.size())
258 , _pathToObj(p2o)
259 , _lastPathDepth(0) {}
260
262 PathToObject &&p2o)
263 : _eval(eval)
264 , _incrSearchStates(_eval->_patternImpls.size())
265 , _pathToObj(std::move(p2o))
266 , _lastPathDepth(0) {}
267
279 Next(SdfPath const &objPath) {
280 auto patternImplIter = _eval->_patternImpls.begin();
281 auto stateIter = _incrSearchStates.begin();
282 int newDepth = objPath.GetPathElementCount();
283 const int popLevel = (newDepth <= _lastPathDepth) ? newDepth : 0;
284 auto patternStateNext = [&](bool skip) {
285 if (popLevel) {
286 stateIter->Pop(popLevel);
287 }
288 return skip
289 ? (++patternImplIter, SdfPredicateFunctionResult())
290 : (*patternImplIter++).Next(objPath, *stateIter++,
291 _pathToObj);
292 };
293 _lastPathDepth = newDepth;
294 return _eval->_EvalExpr(patternStateNext);
295 }
296
299 void Reset() {
300 *this = IncrementalSearcher { _eval, std::move(_pathToObj) };
301 }
302
303 private:
304 SdfPathExpressionEval const *_eval;
305 std::vector<_PatternIncrSearchState> _incrSearchStates;
306
307 PathToObject _pathToObj;
308
309 int _lastPathDepth;
310 };
311
314 template <class PathToObject>
315 IncrementalSearcher<std::decay_t<PathToObject>>
316 MakeIncrementalSearcher(PathToObject &&pathToObj) const {
318 this, std::forward<PathToObject>(pathToObj));
319 }
320
321private:
322 std::vector<_PatternImpl> _patternImpls;
323};
324
336template <class DomainType>
338SdfMakePathExpressionEval(SdfPathExpression const &expr,
340{
341 using Expr = SdfPathExpression;
343
344 Eval eval;
345
346 auto translatePattern = [&](Expr::PathPattern const &pattern) {
347 // Add a _PatternImpl object that tests a DomainType object against
348 // pattern.
349 eval._patternImpls.emplace_back(pattern, lib);
350 eval._ops.push_back(Eval::EvalPattern);
351 };
352
353 if (!Sdf_MakePathExpressionEvalImpl(eval, expr, translatePattern)) {
354 eval = {};
355 }
356
357 return eval;
358}
359
360PXR_NAMESPACE_CLOSE_SCOPE
361
362#endif // PXR_USD_SDF_PATH_EXPRESSION_EVAL_H
This class implements stateful incremental search over DomainType objects in depth-first order.
void Reset()
Reset this object's incremental search state so that a new round of searching may begin.
SdfPredicateFunctionResult Next(SdfPath const &objPath)
Advance the search to the next objPath, and return the result of evaluating the expression on it.
Objects of this class evaluate complete SdfPathExpressions.
friend SdfPathExpressionEval SdfMakePathExpressionEval(SdfPathExpression const &expr, SdfPredicateLibrary< DomainType > const &lib)
Make an SdfPathExpressionEval object to evaluate expr using lib to link any embedded predicate expres...
IncrementalSearcher< std::decay_t< PathToObject > > MakeIncrementalSearcher(PathToObject &&pathToObj) const
Create an IncrementalSearcher object, using pathToObject to map DomainType instances to their paths.
SdfPredicateFunctionResult Match(SdfPath const &objPath, PathToObject const &pathToObj) const
Test objPath for a match with this expression.
Objects of this class represent a logical expression syntax tree consisting of SdfPathPattern s,...
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:274
SDF_API size_t GetPathElementCount() const
Returns the number of path elements in this path.
Objects of this class represent SdfPath matching patterns, consisting of an SdfPath prefix followed b...
Definition: pathPattern.h:31
Represents a logical expression syntax tree consisting of predicate function calls joined by the logi...
Represents the result of a predicate function: a pair of the boolean result and a Constancy token ind...
static SdfPredicateFunctionResult MakeConstant(bool value)
Create with value and 'ConstantOverDescendants'.
Represents a library of predicate functions for use with SdfPredicateExpression.
This class provides a non-owning reference to a type-erased callable object with a specified signatur...
Definition: functionRef.h:19