HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pathExpressionEval.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_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"
33 
34 #include "pxr/base/arch/regex.h"
36 
37 #include <string>
38 #include <type_traits>
39 #include <vector>
40 
42 
43 // fwd decl
44 template <class DomainType>
46 
47 // fwd decl
48 template <class DomainType>
52 
53 // fwd decl
55 
56 // fwd decl
57 SDF_API
58 bool
61  SdfPathExpression const &expr,
63  void (SdfPathExpression::PathPattern const &)> translatePattern);
64 
65 // Helper base class for SdfPathExpressionEval. This factors out as much
66 // template-parameter independent code as possible to reduce bloat & compile
67 // times.
69 {
70 public:
71  friend bool
74  SdfPathExpression const &expr,
76  void (SdfPathExpression::PathPattern const &)> translatePattern);
77 
78  /// Return true if this is the empty evalutator. The empty evaluator always
79  /// returns false from operator().
80  bool IsEmpty() const {
81  return _ops.empty();
82  }
83 
84  /// Return true if this is not the empty evaluator, false otherwise.
85  explicit operator bool() const {
86  return !IsEmpty();
87  }
88 
89 protected:
91  protected:
92  // This is not a constructor because the subclass wants to invoke this
93  // from its ctor, TfFunctionRef currently requires an lvalue, which is
94  // hard to conjure in a ctor initializer list.
95  SDF_API
96  void _Init(SdfPathExpression::PathPattern const &pattern,
98  int (SdfPredicateExpression const &)> linkPredicate);
99 
100  SDF_API
101  bool _Match(SdfPath const &path,
103  bool (int, SdfPath const &)> runNthPredicate) const;
104 
106  Stretch, // the "//", arbitrary levels of hierarchy.
107  ExplicitName, // an explicit name (not a glob pattern).
108  Regex // a glob pattern (handled via regex).
109  };
110 
111  struct _Component {
113  int patternIndex; // into either _explicitNames or _regexes
114  int predicateIndex; // into _predicates or -1 if no predicate.
115  };
116 
118  std::vector<_Component> _components;
119  std::vector<std::string> _explicitNames;
120  std::vector<ArchRegex> _regexes;
121  size_t _numMatchingComponents; // of type ExplicitName or Regex.
122  bool _isProperty; // true if this pattern matches only properties.
123  };
124 
125  // The passed \p patternMatch function must do two things: 1, if \p skip is
126  // false, test the current pattern for a match (otherwise skip it) and 2,
127  // advance to be ready to test the next pattern for a match on the next call
128  // to \p patternMatch.
129  SDF_API
130  bool _Match(TfFunctionRef<bool (bool /*skip*/)> patternMatch) const;
131 
132  enum _Op { PatternMatch, Not, Open, Close, Or, And };
133 
134  std::vector<_Op> _ops;
135 };
136 
137 
138 /// \class SdfPathExpressionEval
139 ///
140 /// Objects of this class evaluate complete SdfPathExpressions on instances of
141 /// DomainType. See SdfMakePathExpressionEval() to create instances of this
142 /// class, passing the expression to evaluate and an
143 /// SdfPredicateLibrary<DomainType> to evaluate any embedded predicates.
144 ///
145 /// This class must be able to find the DomainType instance associated with an
146 /// SdfPath and vice-versa. There are two ways to do this; either explicitly by
147 /// passing function objects to Match(), or by providing ADL-found overloads of
148 /// the following two functions:
149 ///
150 /// \code
151 /// SdfPath SdfPathExpressionObjectToPath(DomainType);
152 /// DomainType SdfPathExpressionPathToObject(SdfPath const &,
153 /// DomainType const *);
154 /// \endcode
155 ///
156 /// The function SdfPathExpressionPathToObject()'s second argument is always
157 /// nullptr. It exists to disambiguate overloads, since functions cannot be
158 /// overloaded on return-type. It is also an argument rather than an explicit
159 /// template parameter since function calls with explicit template arguments are
160 /// not found via ADL.
161 ///
162 template <class DomainType>
164 {
165  struct _DefaultToPath {
166  auto operator()(DomainType obj) const {
167  return SdfPathExpressionObjectToPath(obj);
168  }
169  };
170 
171  struct _DefaultToObj {
172  auto operator()(SdfPath const &path) const {
173  return SdfPathExpressionPathToObject(
174  path, static_cast<std::decay_t<DomainType> const *>(nullptr));
175  }
176  };
177 
178 public:
179  /// Make an SdfPathExpressionEval object to evaluate \p expr using \p lib to
180  /// link any embedded predicate expressions.
181  friend SdfPathExpressionEval
182  SdfMakePathExpressionEval<DomainType>(
183  SdfPathExpression const &expr,
185 
186  /// Test \p obj for a match with this expression. Overloads of
187  /// SdfPathExpressionPathToObject() and SdfPathExpressionObjectToPath() for
188  /// \a DomainType must be found by ADL.
189  bool Match(DomainType obj) {
190  return Match(obj, _DefaultToPath {}, _DefaultToObj {});
191  }
192 
193  /// Test \p obj for a match with this expression. Use \p objToPath and \p
194  /// pathToObj to map between corresponding SdfPath and DomainType instances.
195  template <class ObjectToPath, class PathToObject>
196  bool Match(DomainType obj,
197  ObjectToPath const &objToPath,
198  PathToObject const &pathToObj) const {
199  auto matchIter = _matches.cbegin();
200  auto patternMatch = [&](bool skip) {
201  if (skip) {
202  ++matchIter;
203  return false;
204  }
205  return (*matchIter++)(obj, objToPath, pathToObj);
206  };
207  return _Match(patternMatch);
208  }
209 
210 private:
211 
212  // This object implements matching against a single path pattern.
213  class _PatternMatch : public _PatternMatchBase {
214  public:
215  _PatternMatch(SdfPathExpression::PathPattern const &pattern,
216  SdfPredicateLibrary<DomainType> const &predLib) {
217  auto linkPredicate =
218  [this, &predLib](SdfPredicateExpression const &predExpr) {
219  _predicates.push_back(
220  SdfLinkPredicateExpression(predExpr, predLib));
221  return _predicates.size()-1;
222  };
223  _Init(pattern, linkPredicate);
224  }
225 
226  // Check obj for a match against this pattern.
227  template <class ObjectToPath, class PathToObject>
228  bool operator()(DomainType obj,
229  ObjectToPath const &objToPath,
230  PathToObject const &pathToObj) const {
231  auto runNthPredicate =
232  [this, &pathToObj](int i, SdfPath const &path) {
233  return _predicates[i](pathToObj(path));
234  };
235  return _Match(objToPath(obj), runNthPredicate);
236  }
237 
238  private:
239  std::vector<SdfPredicateProgram<DomainType>> _predicates;
240  };
241 
242  std::vector<_PatternMatch> _matches;
243 };
244 
245 /// Create an SdfPathExpressionEval object that can evaluate the complete
246 /// SdfPathExpression \p expr on DomainType instances, using \p lib, an
247 /// SdfPredicateLibrary<DomainType> to evaluate any embedded predicates.
248 ///
249 /// Note that \p expr must be "complete", meaning that
250 /// SdfPathExpression::IsComplete() must return true. If an evaluator cannot
251 /// succesfully be made, possibly because the passed \expr is not complete, or
252 /// if any embedded SdfPredicateExpression s cannot be successfully linked with
253 /// \p lib, or another reason, issue an error and return the empty
254 /// SdfPathExpressionEval object. See SdfPathExpressionEval::IsEmpty().
255 ///
256 template <class DomainType>
260 {
261  using Expr = SdfPathExpression;
263 
264  Eval eval;
265 
266  auto translatePattern = [&](Expr::PathPattern const &pattern) {
267  // Add a _PatternMatch object that tests a DomainType object against
268  // pattern.
269  eval._matches.emplace_back(pattern, lib);
270  eval._ops.push_back(Eval::PatternMatch);
271  };
272 
273  if (!Sdf_MakePathExpressionEvalImpl(eval, expr, translatePattern)) {
274  eval = {};
275  }
276 
277  return eval;
278 }
279 
281 
282 #endif // PXR_USD_SDF_PATH_EXPRESSION_EVAL_H
SDF_API bool _Match(TfFunctionRef< bool(bool)> patternMatch) const
void skip(T &in, int n)
Definition: ImfXdr.h:711
SdfPredicateProgram< DomainType > SdfLinkPredicateExpression(SdfPredicateExpression const &expr, SdfPredicateLibrary< DomainType > const &lib)
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
friend bool Sdf_MakePathExpressionEvalImpl(Sdf_PathExpressionEvalBase &eval, SdfPathExpression const &expr, TfFunctionRef< void(SdfPathExpression::PathPattern const &)> translatePattern)
SDF_API bool Sdf_MakePathExpressionEvalImpl(Sdf_PathExpressionEvalBase &eval, SdfPathExpression const &expr, TfFunctionRef< void(SdfPathExpression::PathPattern const &)> translatePattern)
SDF_API void _Init(SdfPathExpression::PathPattern const &pattern, TfFunctionRef< int(SdfPredicateExpression const &)> linkPredicate)
HUSD_API bool eval(VtValue &val, T &ret_val)
Definition: path.h:291
SDF_API bool _Match(SdfPath const &path, TfFunctionRef< bool(int, SdfPath const &)> runNthPredicate) const
GLushort pattern
Definition: glad.h:2583
#define SDF_API
Definition: api.h:40
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
SdfPathExpressionEval< DomainType > SdfMakePathExpressionEval(SdfPathExpression const &expr, SdfPredicateLibrary< DomainType > const &lib)
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
bool Match(DomainType obj)
bool Match(DomainType obj, ObjectToPath const &objToPath, PathToObject const &pathToObj) const