HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_PathPattern.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  */
7 
8 #ifndef __UT_PathPattern_h__
9 #define __UT_PathPattern_h__
10 
11 #include "UT_API.h"
12 #include "UT_Array.h"
13 #include "UT_IntArray.h"
14 #include "UT_IntrusivePtr.h"
15 #include "UT_StringHolder.h"
16 #include "UT_StringArray.h"
17 #include "UT_UniquePtr.h"
18 
19 class UT_SpecialTokenData : public UT_IntrusiveRefCounter<UT_SpecialTokenData>
20 {
21 public:
23  { }
25  { }
26 };
28 
29 // Optional opaque payload carried alongside the boolean result of a pattern
30 // match. The base class never creates these, so base-class matching stays
31 // purely boolean. Subclasses (e.g. the USD path pattern) use them to carry and
32 // combine per-match data, such as the set of matched point instancer
33 // instances, according to the pattern's set operators. See the matches()
34 // overload that takes a match_data argument.
36  : public UT_IntrusiveRefCounter<UT_PathPatternMatchData>
37 {
38 public:
40  { }
42  { }
43 };
45 
46 // Matches a pattern against a USD path. The pattern uses roughly rsync style
47 // matching, where "*" only matches within a path component, and "**" matches
48 // across path components. Also supports standard Houdini "^" operator to
49 // exclude paths. In addition, "-" will also exclude paths, "&" will perform
50 // intersections between two sets of paths, and "~" can be used to quickly
51 // prune branches during a full traversal of the path hierarchy.
53 {
54 public:
56  bool case_sensitive = true,
57  bool assume_wildcards = false,
58  bool allow_instance_indices = false);
59  virtual ~UT_PathPattern();
60 
61  bool matches(const UT_StringRef &path,
62  bool *excludes_branch = nullptr) const;
63  // As above, but also returns an optional opaque payload describing the
64  // match. Subclasses use this to carry a per-match instance selection that
65  // is combined according to the pattern's set operators (union, intersect,
66  // difference). For the base class, match_data is always cleared to null
67  // and this behaves exactly like the plain matches() above.
68  bool matches(const UT_StringRef &path,
69  bool *excludes_branch,
70  UT_PathPatternMatchDataPtr &match_data) const;
71  bool getExplicitList(UT_StringArray &tokens) const;
72  bool getExplicitListWithInstanceIds(
73  UT_StringArray &paths,
74  UT_StringArray &instance_patterns) const;
75 
76  bool getCaseSensitive() const
77  { return myCaseSensitive; }
79  { return myAssumeWildcardsAroundPlainTokens; }
81  { return myAllowInstanceIndices; }
83  { return myPatternError; }
84 
85 protected:
86  class Token
87  {
88  public:
89  Token(const UT_StringHolder &str,
90  bool do_path_matching,
91  bool has_wildcards)
92  : myString(str),
93  myDoPathMatching(do_path_matching),
94  myHasWildcards(has_wildcards),
95  myIsSpecialToken(false)
96  { }
97 
104  };
105 
106  // Default constructor, only to be used by createEmptyClone, which is used
107  // by create* functions to build a new patterns from pieces of the current
108  // pattern.
109  UT_PathPattern(bool case_sensitive,
110  bool assume_wildcards,
111  bool allow_instance_indices);
112 
113  UT_PathPattern *createPruningPattern(int tokenidx);
114  UT_PathPattern *createPrecedingGroupPattern(int tokenidx);
116  {
117  return new UT_PathPattern(myCaseSensitive,
118  myAssumeWildcardsAroundPlainTokens,
119  myAllowInstanceIndices);
120  }
121  virtual bool matchSpecialToken(
122  const UT_StringRef &path,
123  const Token &token,
124  bool *excludes_branch) const;
125 
126  // Set operations used when combining match payloads from the left and
127  // right sides of a pattern operator.
128  enum MatchOp
129  {
130  MATCH_ADD, // union (space, "+")
131  MATCH_SUBTRACT, // difference ("-", "^")
132  MATCH_INTERSECT, // intersection ("&")
133  MATCH_PRUNE // pruning ("~"); payload passes through unchanged
134  };
135 
136  // Hooks allowing a subclass to carry an opaque payload through the match
137  // evaluation. The base implementations produce no payload, so base-class
138  // matching is purely boolean and entirely unchanged. The USD subclasses
139  // use these to carry and combine the set of matched point instancer
140  // instances for a given path. These are only invoked during a match when
141  // the caller requested a payload (the matches() overload above).
143  const UT_StringRef &path,
144  const Token &token,
145  bool *excludes_branch,
146  UT_PathPatternMatchDataPtr &match_data) const
147  {
148  return matchSpecialToken(path, token,
149  excludes_branch);
150  }
152  const UT_StringRef &path,
153  const Token &token) const
154  { return UT_PathPatternMatchDataPtr(); }
156  MatchOp op,
157  const UT_PathPatternMatchDataPtr &lhs,
158  const UT_PathPatternMatchDataPtr &rhs) const
159  { return UT_PathPatternMatchDataPtr(); }
160  virtual bool matchDataIsEmpty(
161  const UT_PathPatternMatchDataPtr &match_data)
162  const
163  { return !match_data; }
164 
165  void testForExplicitList();
166  void patternInterrupted();
167 
169 
170 private:
171  // This class is used to represent the parsed expression tree generated
172  // from a string search pattern.
173  class PatternOp
174  {
175  public:
176  enum Operator
177  {
178  GROUP,
179  NOOP,
180  VALUES,
181  ADD,
182  SUBTRACT,
183  PRUNE,
184  INTERSECT
185  };
186 
187  PatternOp(const UT_PathPattern &owner)
188  : myOwner(owner),
189  myOp(GROUP),
190  myParent(nullptr)
191  { }
192  PatternOp(PatternOp &parent, Operator op)
193  : myOwner(parent.myOwner),
194  myOp(op),
195  myParent(&parent)
196  { }
197 
198  PatternOp *push(Operator op);
199  PatternOp *insertGroup();
200  bool containsOnlyAddOperations() const;
201 
202  PatternOp *leftOp() { return myLeftOp.get(); }
203  const PatternOp *leftOp() const { return myLeftOp.get(); }
204  PatternOp *rightOp() { return myRightOp.get(); }
205  const PatternOp *rightOp() const { return myRightOp.get(); }
206 
207  const UT_PathPattern &myOwner;
208  Operator myOp;
209  PatternOp *myParent;
210  UT_UniquePtr<PatternOp> myLeftOp;
211  UT_UniquePtr<PatternOp> myRightOp;
212  UT_IntArray myValues;
213  };
214 
215  class PatternOpStep
216  {
217  public:
218  PatternOpStep(PatternOp *op = nullptr)
219  : myPatternOp(op), myFollowLeftChild(false) { }
220 
221  PatternOp *myPatternOp;
222  bool myFollowLeftChild;
223  };
224 
225  typedef UT_Array<PatternOpStep> PatternOpPath;
226 
227  void init(const UT_StringArray &pattern_tokens);
228  bool matches(const UT_StringRef &path,
229  const PatternOp *op,
230  bool *excludes_branch,
231  UT_PathPatternMatchDataPtr *match_data
232  = nullptr) const;
233  // Combine left/right payloads for a binary operator and derive the new
234  // boolean result. When a payload is produced (instance-relevant paths),
235  // membership follows whether the combined set is non-empty; otherwise the
236  // supplied boolean result is kept unchanged.
237  bool combineAndUpdateMatchData(MatchOp op,
238  const UT_PathPatternMatchDataPtr &lhs,
239  const UT_PathPatternMatchDataPtr &rhs,
240  bool boolean_matched,
241  UT_PathPatternMatchDataPtr &out) const;
242  void printPattern(const PatternOp *patternop,
243  int indent);
244  static bool findToken(int tokenidx,
245  PatternOpPath &oppath);
246  static UT_UniquePtr<PatternOp> duplicatePatternOp(
247  const UT_PathPattern &pattern,
248  const PatternOp *patternop,
249  PatternOp *parent);
250  static bool patternOpPathContains(
251  const PatternOpPath &oppath,
252  const PatternOp *patternop);
253  static bool patternOpPathIntersects(
254  const PatternOpPath &oppath,
255  const PatternOp *patternop);
256  static void makePruningPatternOp(
257  PatternOp *patternop,
258  const PatternOpPath &oppath);
259  static void makePrecedingGroupPatternOp(
260  PatternOp *patternop,
261  const PatternOpPath &oppath,
262  bool &found_token);
263  static bool parsePattern(const char *&pattern,
264  UT_StringArray &tokens,
265  PatternOp *groupop,
266  UT_String &error);
267 
268  UT_UniquePtr<PatternOp> myPatternOp;
269  UT_StringHolder myPatternError;
270  bool myIsExplicitList;
271  // These values can't change after the constructor, because the
272  // constructor can cause evaluation of the pattern or parts of it.
273  const bool myCaseSensitive;
274  const bool myAssumeWildcardsAroundPlainTokens;
275  const bool myAllowInstanceIndices;
276 };
277 
278 #endif
279 
*pool push(my_func, arg1,...)
UT_StringHolder myInstanceIdPattern
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
bool getAllowInstanceIndices() const
#define UT_API
Definition: UT_API.h:14
virtual bool matchDataIsEmpty(const UT_PathPatternMatchDataPtr &match_data) const
const UT_StringHolder & getPatternError() const
A reference counter base class for use with UT_IntrusivePtr.
virtual ~UT_PathPatternMatchData()
bool getCaseSensitive() const
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
< returns > If no error
Definition: snippets.dox:2
UT_Array< Token > myTokens
virtual UT_PathPatternMatchDataPtr combineMatchData(MatchOp op, const UT_PathPatternMatchDataPtr &lhs, const UT_PathPatternMatchDataPtr &rhs) const
bool getAssumeWildcardsAroundPlainTokens() const
UT_IntrusivePtr< UT_SpecialTokenData > UT_SpecialTokenDataPtr
Token(const UT_StringHolder &str, bool do_path_matching, bool has_wildcards)
GLushort pattern
Definition: glad.h:2583
virtual ~UT_SpecialTokenData()
UT_StringHolder myString
virtual UT_PathPatternMatchDataPtr makeLeafMatchData(const UT_StringRef &path, const Token &token) const
virtual bool matchSpecialTokenWithData(const UT_StringRef &path, const Token &token, bool *excludes_branch, UT_PathPatternMatchDataPtr &match_data) const
virtual UT_PathPattern * createEmptyClone() const
UT_SpecialTokenDataPtr mySpecialTokenDataPtr
UT_IntrusivePtr< UT_PathPatternMatchData > UT_PathPatternMatchDataPtr