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 enum : uint8_t {
155 // The kind of objects this pattern is capable of matching.
156 _MatchPrimOrProp, _MatchPrimOnly, _MatchPropOnly
157 } _matchObjType;
158 };
159
160
161 // The passed \p invokePattern function must do two things: 1, if \p skip is
162 // false, test the current pattern for a match (otherwise skip it) and 2,
163 // advance to be ready to test the next pattern for a match on the next call
164 // to \p invokePattern.
165 SDF_API
167 _EvalExpr(TfFunctionRef<
168 SdfPredicateFunctionResult (bool /*skip*/)> invokePattern) const;
169
170 enum _Op { EvalPattern, Not, Open, Close, Or, And };
171
172 std::vector<_Op> _ops;
173};
174
183template <class DomainType>
184class SdfPathExpressionEval : public Sdf_PathExpressionEvalBase
185{
186 // This object implements matching against a single path pattern.
187 class _PatternImpl : public _PatternImplBase {
188 public:
189 _PatternImpl() = default;
190
191 _PatternImpl(SdfPathExpression::PathPattern const &pattern,
192 SdfPredicateLibrary<DomainType> const &predLib) {
193 auto linkPredicate =
194 [this, &predLib](SdfPredicateExpression const &predExpr) {
195 _predicates.push_back(
196 SdfLinkPredicateExpression(predExpr, predLib));
197 return _predicates.size()-1;
198 };
199 _Init(pattern, linkPredicate);
200 }
201
202 // Check objPath for a match against this pattern.
203 template <class PathToObject>
205 Match(SdfPath const &objPath,
206 PathToObject const &pathToObj) const {
207 auto runNthPredicate =
208 [this, &pathToObj](int i, SdfPath const &path) {
209 return _predicates[i](pathToObj(path));
210 };
211 return _Match(objPath, runNthPredicate);
212 }
213
214 // Perform the next incremental search step against this pattern.
215 template <class PathToObject>
217 Next(SdfPath const &objPath,
218 _PatternIncrSearchState &search,
219 PathToObject const &pathToObj) const {
220 auto runNthPredicate =
221 [this, &pathToObj](int i, SdfPath const &path) {
222 return _predicates[i](pathToObj(path));
223 };
224 return _Next(search, objPath, runNthPredicate);
225 }
226
227 private:
228 std::vector<SdfPredicateProgram<DomainType>> _predicates;
229 };
230
231public:
235 SdfMakePathExpressionEval<DomainType>(
236 SdfPathExpression const &expr,
238
239 bool IsEmpty() const {
240 return _patternImpls.empty();
241 }
242
244 template <class PathToObject>
246 Match(SdfPath const &objPath,
247 PathToObject const &pathToObj) const {
248 if (IsEmpty()) {
250 }
251 auto patternImplIter = _patternImpls.cbegin();
252 auto evalPattern = [&](bool skip) {
253 return skip ? (++patternImplIter, SdfPredicateFunctionResult()) :
254 (*patternImplIter++).Match(objPath, pathToObj);
255 };
256 return _EvalExpr(evalPattern);
257 }
258
266 template <class PathToObject>
268 public:
269 IncrementalSearcher() : _eval(nullptr), _lastPathDepth(0) {}
270
272 PathToObject const &p2o)
273 : _eval(eval)
274 , _incrSearchStates(_eval->_patternImpls.size())
275 , _pathToObj(p2o)
276 , _lastPathDepth(0) {}
277
279 PathToObject &&p2o)
280 : _eval(eval)
281 , _incrSearchStates(_eval->_patternImpls.size())
282 , _pathToObj(std::move(p2o))
283 , _lastPathDepth(0) {}
284
296 Next(SdfPath const &objPath) {
297 auto patternImplIter = _eval->_patternImpls.begin();
298 auto stateIter = _incrSearchStates.begin();
299 int newDepth = objPath.GetPathElementCount();
300 const int popLevel = (newDepth <= _lastPathDepth) ? newDepth : 0;
301 auto patternStateNext = [&](bool skip) {
302 if (popLevel) {
303 stateIter->Pop(popLevel);
304 }
305 return skip
306 ? (++patternImplIter, SdfPredicateFunctionResult())
307 : (*patternImplIter++).Next(objPath, *stateIter++,
308 _pathToObj);
309 };
310 _lastPathDepth = newDepth;
311 return _eval->_EvalExpr(patternStateNext);
312 }
313
316 void Reset() {
317 *this = IncrementalSearcher { _eval, std::move(_pathToObj) };
318 }
319
320 private:
321 SdfPathExpressionEval const *_eval;
322 std::vector<_PatternIncrSearchState> _incrSearchStates;
323
324 PathToObject _pathToObj;
325
326 int _lastPathDepth;
327 };
328
331 template <class PathToObject>
332 IncrementalSearcher<std::decay_t<PathToObject>>
333 MakeIncrementalSearcher(PathToObject &&pathToObj) const {
335 this, std::forward<PathToObject>(pathToObj));
336 }
337
338private:
339 std::vector<_PatternImpl> _patternImpls;
340};
341
353template <class DomainType>
355SdfMakePathExpressionEval(SdfPathExpression const &expr,
357{
358 using Expr = SdfPathExpression;
360
361 Eval eval;
362
363 auto translatePattern = [&](Expr::PathPattern const &pattern) {
364 // Add a _PatternImpl object that tests a DomainType object against
365 // pattern.
366 eval._patternImpls.emplace_back(pattern, lib);
367 eval._ops.push_back(Eval::EvalPattern);
368 };
369
370 if (!Sdf_MakePathExpressionEvalImpl(eval, expr, translatePattern)) {
371 eval = {};
372 }
373
374 return eval;
375}
376
377PXR_NAMESPACE_CLOSE_SCOPE
378
379#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