Loading...
Searching...
No Matches
pathExpressionEval.h
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_PATH_EXPRESSION_EVAL_H
25#define PXR_USD_SDF_PATH_EXPRESSION_EVAL_H
26
27#include "pxr/pxr.h"
28#include "pxr/usd/sdf/api.h"
29#include "pxr/usd/sdf/path.h"
30#include "pxr/usd/sdf/pathExpression.h"
31#include "pxr/usd/sdf/predicateExpression.h"
32#include "pxr/usd/sdf/predicateLibrary.h"
33#include "pxr/usd/sdf/predicateProgram.h"
34
35#include "pxr/base/arch/regex.h"
36#include "pxr/base/tf/functionRef.h"
37
38#include <string>
39#include <type_traits>
40#include <vector>
41
42PXR_NAMESPACE_OPEN_SCOPE
43
44// fwd decl
45template <class DomainType>
47
48// fwd decl
49template <class DomainType>
53
54// fwd decl
55class Sdf_PathExpressionEvalBase;
56
57// Helper base class for SdfPathExpressionEval. This factors out as much
58// template-parameter independent code as possible to reduce bloat & compile
59// times.
60class Sdf_PathExpressionEvalBase
61{
62public:
63 friend SDF_API bool
64 Sdf_MakePathExpressionEvalImpl(
65 Sdf_PathExpressionEvalBase &eval,
66 SdfPathExpression const &expr,
68 void (SdfPathExpression::PathPattern const &)> translatePattern);
69
72 bool IsEmpty() const {
73 return _ops.empty();
74 }
75
77 explicit operator bool() const {
78 return !IsEmpty();
79 }
80
81protected:
82 class _PatternImplBase;
83
84 class _PatternIncrSearchState {
85 friend class _PatternImplBase;
86 public:
87 void Pop(int newDepth) {
88 while (!_segmentMatchDepths.empty() &&
89 _segmentMatchDepths.back() >= newDepth) {
90 _segmentMatchDepths.pop_back();
91 }
92 if (newDepth <= _constantDepth) {
93 _constantDepth = -1;
94 }
95 }
96 private:
97 std::vector<int> _segmentMatchDepths;
98 int _constantDepth = -1; // 0 means constant at the _prefix level.
99 bool _constantValue = false;
100 };
101
102 class _PatternImplBase {
103 protected:
104 // This is not a constructor because the subclass wants to invoke this
105 // from its ctor, TfFunctionRef currently requires an lvalue, which is
106 // hard to conjure in a ctor initializer list.
107 SDF_API
108 void _Init(SdfPathExpression::PathPattern const &pattern,
110 int (SdfPredicateExpression const &)> linkPredicate);
111
112 SDF_API
114 _Match(
115 SdfPath const &path,
117 runNthPredicate) const;
118
119 SDF_API
121 _Next(_PatternIncrSearchState &searchState,
122 SdfPath const &path,
124 runNthPredicate) const;
125
126 enum _ComponentType {
127 ExplicitName, // an explicit name (not a glob pattern).
128 Regex // a glob pattern (handled via regex).
129 };
130
131 struct _Component {
132 _ComponentType type;
133 int patternIndex; // into either _explicitNames or _regexes
134 int predicateIndex; // into _predicates or -1 if no predicate.
135 };
136
137 struct _Segment {
138 // A _Segment is a half-open interval [begin, end) in _components.
139 bool IsEmpty() const { return begin == end; }
140 bool StartsAt(size_t idx) const { return begin == idx; }
141 bool EndsAt(size_t idx) const { return end == idx; }
142 size_t GetSize() const { return end - begin; }
143 size_t begin, end;
144 };
145
146 SdfPath _prefix;
147 std::vector<_Component> _components;
148 std::vector<_Segment> _segments;
149 std::vector<std::string> _explicitNames;
150 std::vector<ArchRegex> _regexes;
151
152 bool _stretchBegin;
153 bool _stretchEnd;
154 bool _isProperty; // true if this pattern matches only properties.
155 };
156
157
158 // The passed \p invokePattern function must do two things: 1, if \p skip is
159 // false, test the current pattern for a match (otherwise skip it) and 2,
160 // advance to be ready to test the next pattern for a match on the next call
161 // to \p invokePattern.
162 SDF_API
164 _EvalExpr(TfFunctionRef<
165 SdfPredicateFunctionResult (bool /*skip*/)> invokePattern) const;
166
167 enum _Op { EvalPattern, Not, Open, Close, Or, And };
168
169 std::vector<_Op> _ops;
170};
171
180template <class DomainType>
181class SdfPathExpressionEval : public Sdf_PathExpressionEvalBase
182{
183 // This object implements matching against a single path pattern.
184 class _PatternImpl : public _PatternImplBase {
185 public:
186 _PatternImpl() = default;
187
188 _PatternImpl(SdfPathExpression::PathPattern const &pattern,
189 SdfPredicateLibrary<DomainType> const &predLib) {
190 auto linkPredicate =
191 [this, &predLib](SdfPredicateExpression const &predExpr) {
192 _predicates.push_back(
193 SdfLinkPredicateExpression(predExpr, predLib));
194 return _predicates.size()-1;
195 };
196 _Init(pattern, linkPredicate);
197 }
198
199 // Check objPath for a match against this pattern.
200 template <class PathToObject>
202 Match(SdfPath const &objPath,
203 PathToObject const &pathToObj) const {
204 auto runNthPredicate =
205 [this, &pathToObj](int i, SdfPath const &path) {
206 return _predicates[i](pathToObj(path));
207 };
208 return _Match(objPath, runNthPredicate);
209 }
210
211 // Perform the next incremental search step against this pattern.
212 template <class PathToObject>
214 Next(SdfPath const &objPath,
215 _PatternIncrSearchState &search,
216 PathToObject const &pathToObj) const {
217 auto runNthPredicate =
218 [this, &pathToObj](int i, SdfPath const &path) {
219 return _predicates[i](pathToObj(path));
220 };
221 return _Next(search, objPath, runNthPredicate);
222 }
223
224 private:
225 std::vector<SdfPredicateProgram<DomainType>> _predicates;
226 };
227
228public:
232 SdfMakePathExpressionEval<DomainType>(
233 SdfPathExpression const &expr,
235
236 bool IsEmpty() const {
237 return _patternImpls.empty();
238 }
239
241 template <class PathToObject>
243 Match(SdfPath const &objPath,
244 PathToObject const &pathToObj) const {
245 if (IsEmpty()) {
247 }
248 auto patternImplIter = _patternImpls.cbegin();
249 auto evalPattern = [&](bool skip) {
250 return skip ? (++patternImplIter, SdfPredicateFunctionResult()) :
251 (*patternImplIter++).Match(objPath, pathToObj);
252 };
253 return _EvalExpr(evalPattern);
254 }
255
263 template <class PathToObject>
265 public:
266 IncrementalSearcher() : _eval(nullptr), _lastPathDepth(0) {}
267
269 PathToObject const &p2o)
270 : _eval(eval)
271 , _incrSearchStates(_eval->_patternImpls.size())
272 , _pathToObj(p2o)
273 , _lastPathDepth(0) {}
274
276 PathToObject &&p2o)
277 : _eval(eval)
278 , _incrSearchStates(_eval->_patternImpls.size())
279 , _pathToObj(std::move(p2o))
280 , _lastPathDepth(0) {}
281
293 Next(SdfPath const &objPath) {
294 auto patternImplIter = _eval->_patternImpls.begin();
295 auto stateIter = _incrSearchStates.begin();
296 int newDepth = objPath.GetPathElementCount();
297 const int popLevel = (newDepth <= _lastPathDepth) ? newDepth : 0;
298 auto patternStateNext = [&](bool skip) {
299 if (popLevel) {
300 stateIter->Pop(popLevel);
301 }
302 return skip
303 ? (++patternImplIter, SdfPredicateFunctionResult())
304 : (*patternImplIter++).Next(objPath, *stateIter++,
305 _pathToObj);
306 };
307 _lastPathDepth = newDepth;
308 return _eval->_EvalExpr(patternStateNext);
309 }
310
313 void Reset() {
314 *this = IncrementalSearcher { _eval, std::move(_pathToObj) };
315 }
316
317 private:
318 SdfPathExpressionEval const *_eval;
319 std::vector<_PatternIncrSearchState> _incrSearchStates;
320
321 PathToObject _pathToObj;
322
323 int _lastPathDepth;
324 };
325
328 template <class PathToObject>
329 IncrementalSearcher<std::decay_t<PathToObject>>
330 MakeIncrementalSearcher(PathToObject &&pathToObj) const {
332 this, std::forward<PathToObject>(pathToObj));
333 }
334
335private:
336 std::vector<_PatternImpl> _patternImpls;
337};
338
350template <class DomainType>
352SdfMakePathExpressionEval(SdfPathExpression const &expr,
354{
355 using Expr = SdfPathExpression;
357
358 Eval eval;
359
360 auto translatePattern = [&](Expr::PathPattern const &pattern) {
361 // Add a _PatternImpl object that tests a DomainType object against
362 // pattern.
363 eval._patternImpls.emplace_back(pattern, lib);
364 eval._ops.push_back(Eval::EvalPattern);
365 };
366
367 if (!Sdf_MakePathExpressionEvalImpl(eval, expr, translatePattern)) {
368 eval = {};
369 }
370
371 return eval;
372}
373
374PXR_NAMESPACE_CLOSE_SCOPE
375
376#endif // PXR_USD_SDF_PATH_EXPRESSION_EVAL_H
Objects of this class represent SdfPath matching patterns, consisting of an SdfPath prefix followed b...
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 SdfPath matching patte...
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:290
SDF_API size_t GetPathElementCount() const
Returns the number of path elements in this path.
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:36