pathNode.h
1 //
2 // Copyright 2016 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_NODE_H
25 #define PXR_USD_SDF_PATH_NODE_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/usd/sdf/api.h"
29 #include "pxr/base/tf/functionRef.h"
30 #include "pxr/base/tf/token.h"
31 #include "pxr/base/tf/mallocTag.h"
32 
33 #include <boost/noncopyable.hpp>
34 #include <boost/intrusive_ptr.hpp>
35 
36 #include <tbb/atomic.h>
37 
38 PXR_NAMESPACE_OPEN_SCOPE
39 
40 // Sdf_PathNode
41 //
42 // This class is the root of the path node hierarchy. It used to use ordinary
43 // C++ polymorphism, but it no longer does. This is primarily a space
44 // optimization: the set of node types is fixed, we already have an enum 'type'
45 // field, and we typically have lots (e.g. ~1e8) of these objects. Dropping the
46 // C++ polymorphism saves us the vtable pointer, and we can pack the '_nodeType'
47 // field in a much smaller space with other flags.
48 //
49 // We currently store PathNode objects in two prefix trees. The "prim like"
50 // path nodes (the root nodes '/' and '.', prim path nodes, and prim variant
51 // selection nodes are in one prefix tree, and the "property like" nodes are in
52 // another prefix tree (prim property nodes, target nodes, expression nodes,
53 // mapper arg nodes). We do this because there are far fewer unique property
54 // nodes (generally) than there are prim nodes. We allocate these in Sdf_Pools,
55 // so that the SdfPath class can store a handle to an element in each tree in 64
56 // bits total. (Sdf_Pool is designed so that we can refer to objects in memory
57 // using 32-bit indexes instead of 64-bit pointers). An SdfPath joins together
58 // these two elements to form a whole path. For example, the path
59 // '/Foo/Bar.attr' would store a prim-part handle to the '/Foo/Bar' node, and a
60 // property-part handle to 'attr'.
61 //
62 class Sdf_PathNode {
63  Sdf_PathNode(Sdf_PathNode const &) = delete;
64  Sdf_PathNode &operator=(Sdf_PathNode const &) = delete;
65 public:
66  // Node types identify what kind of path node a given instance is.
67  // There are restrictions on what type of children each node type
68  // can have,
69  enum NodeType {
70 
71  /********************************************************/
72  /******************************* Prim portion nodes *****/
73 
74  RootNode,
75  // Allowable child node types:
76  // PrimNode
77  // PrimPropertyNode (only for relative root)
78  // PrimVariantSelectionNode (only for relative root)
79 
80  PrimNode,
81  // Allowable child node types:
82  // PrimNode
83  // PrimPropertyNode
84  // PrimVariantSelectionNode
85 
86  PrimVariantSelectionNode,
87  // Allowable child node types:
88  // PrimNode
89  // PrimPropertyNode
90  // PrimVariantSelectionNode
91  // (for variants that contain variant sets)
92 
93  /********************************************************/
94  /******************************* Property portion nodes */
95 
96  PrimPropertyNode,
97  // Allowable child node types:
98  // TargetNode
99  // MapperNode
100  // ExpressionNode
101 
102  TargetNode,
103  // Allowable child node types:
104  // RelationalAttributeNode (only if parent is PrimPropertyNode)
105 
106  MapperNode,
107  // Allowable child node types:
108  // MapperArgNode
109 
110  RelationalAttributeNode,
111  // Allowable child node types:
112  // TargetNode
113  // MapperNode
114  // ExpressionNode
115 
116  MapperArgNode,
117  // Allowable child node types:
118  // <none>
119 
120  ExpressionNode,
121  // Allowable child node types:
122  // <none>
123 
124  NumNodeTypes
125  };
126 
127  static Sdf_PathPrimNodeHandle
128  FindOrCreatePrim(Sdf_PathNode const *parent, const TfToken &name,
129  TfFunctionRef<bool ()> isValid);
130 
131  static Sdf_PathPropNodeHandle
132  FindOrCreatePrimProperty(
133  Sdf_PathNode const *parent, const TfToken &name,
134  TfFunctionRef<bool ()> isValid);
135 
136  static Sdf_PathPrimNodeHandle
137  FindOrCreatePrimVariantSelection(Sdf_PathNode const *parent,
138  const TfToken &variantSet,
139  const TfToken &variant,
140  TfFunctionRef<bool ()> isValid);
141 
142  static Sdf_PathPropNodeHandle
143  FindOrCreateTarget(Sdf_PathNode const *parent,
144  SdfPath const &targetPath,
145  TfFunctionRef<bool ()> isValid);
146 
147  static Sdf_PathPropNodeHandle
148  FindOrCreateRelationalAttribute(Sdf_PathNode const *parent,
149  const TfToken &name,
150  TfFunctionRef<bool ()> isValid);
151 
152  static Sdf_PathPropNodeHandle
153  FindOrCreateMapper(Sdf_PathNode const *parent, SdfPath const &targetPath,
154  TfFunctionRef<bool ()> isValid);
155 
156  static Sdf_PathPropNodeHandle
157  FindOrCreateMapperArg(Sdf_PathNode const *parent, const TfToken &name,
158  TfFunctionRef<bool ()> isValid);
159 
160  static Sdf_PathPropNodeHandle
161  FindOrCreateExpression(Sdf_PathNode const *parent,
162  TfFunctionRef<bool ()> isValid);
163 
164  static Sdf_PathNode const *GetAbsoluteRootNode();
165  static Sdf_PathNode const *GetRelativeRootNode();
166 
167  NodeType GetNodeType() const { return NodeType(_nodeType); }
168 
169  static std::pair<Sdf_PathNode const *, Sdf_PathNode const *>
170  RemoveCommonSuffix(Sdf_PathNode const *a,
171  Sdf_PathNode const *b,
172  bool stopAtRootPrim);
173 
174  // This method returns a node pointer
175  Sdf_PathNode const *GetParentNode() const { return _parent.get(); }
176 
177  size_t GetElementCount() const { return size_t(_elementCount); }
178  bool IsAbsolutePath() const { return _isAbsolute; }
179  bool IsAbsoluteRoot() const { return (_isAbsolute) & (!_elementCount); }
180  bool ContainsTargetPath() const { return _containsTargetPath; }
181  bool IsNamespaced() const {
182  return (_nodeType == PrimPropertyNode ||
183  _nodeType == RelationalAttributeNode) && _IsNamespacedImpl();
184  }
185 
186  bool ContainsPrimVariantSelection() const {
187  return _containsPrimVariantSelection;
188  }
189 
190  // For PrimNode, PrimPropertyNode, RelationalAttributeNode, and
191  // MapperArgNode this is the name (with no "dot" for
192  // properties/relational attributes/mapper args). For others, it
193  // is EmptyToken.
194  inline const TfToken &GetName() const;
195 
196  // For TargetNode and MapperNode this is the target path.
197  // For others, it is InvalidPath.
198  inline const SdfPath &GetTargetPath() const;
199 
200  typedef std::pair<TfToken, TfToken> VariantSelectionType;
201  inline const VariantSelectionType& GetVariantSelection() const;
202 
203  // Returns the path element string (".name" for properties, "[path]" for
204  // targets, etc...)
205  inline TfToken GetElement() const;
206 
207  // Return the stringified path to this node as a TfToken lvalue.
208  SDF_API static const TfToken &
209  GetPathToken(Sdf_PathNode const *primPart, Sdf_PathNode const *propPart);
210 
211  // Return the stringified path to this node as a TfToken rvalue.
212  SDF_API static TfToken
213  GetPathAsToken(Sdf_PathNode const *primPart, Sdf_PathNode const *propPart);
214 
215  static char const *
216  GetDebugText(Sdf_PathNode const *primPart, Sdf_PathNode const *propPart);
217 
218  // Lexicographic ordering for Compare().
219  struct LessThan {
220  template <class T>
221  inline bool operator()(T const &a, T const &b) const {
222  return a < b;
223  }
224  };
225 
226  // This operator only works properly when the rhs has the same parent
227  // as this node.
228  template <class Less>
229  inline bool Compare(const Sdf_PathNode &rhs) const;
230 
231  // Return the current ref-count.
232  // Meant for diagnostic use.
233  unsigned int GetCurrentRefCount() const { return _refCount; }
234 
235 protected:
236  Sdf_PathNode(Sdf_PathNode const *parent, NodeType nodeType)
237  : _parent(parent)
238  , _refCount(1)
239  , _elementCount(parent ? parent->_elementCount + 1 : 1)
240  , _nodeType(nodeType)
241  , _isAbsolute(parent && parent->IsAbsolutePath())
242  , _containsPrimVariantSelection(
243  nodeType == PrimVariantSelectionNode ||
244  (parent && parent->_containsPrimVariantSelection))
245  , _containsTargetPath(nodeType == TargetNode ||
246  nodeType == MapperNode ||
247  (parent && parent->_containsTargetPath))
248  , _hasToken(false)
249  {}
250 
251  // This constructor is used only to create the two special root nodes.
252  explicit Sdf_PathNode(bool isAbsolute);
253 
254  ~Sdf_PathNode() {
255  if (_hasToken)
256  _RemovePathTokenFromTable();
257  }
258 
259  // Helper to downcast and destroy the dynamic type of this object -- this is
260  // required since this class hierarchy doesn't use normal C++ polymorphism
261  // for space reasons.
262  inline void _Destroy() const;
263 
264  TfToken _GetElementImpl() const;
265 
266  // Helper function for GetPathToken, which lazily creates its token
267  static TfToken _CreatePathToken(Sdf_PathNode const *primPart,
268  Sdf_PathNode const *propPart);
269 
270  template <class Buffer>
271  static void _WriteTextToBuffer(Sdf_PathNode const *primPart,
272  Sdf_PathNode const *propPart,
273  Buffer &out);
274 
275  template <class Buffer>
276  static void _WriteTextToBuffer(SdfPath const &path, Buffer &out);
277 
278  // Append this element's text (same as GetElement()) to \p out.
279  template <class Buffer>
280  void _WriteText(Buffer &out) const;
281 
282  // Helper for dtor, removes this path node's token from the token table.
283  SDF_API void _RemovePathTokenFromTable() const;
284 
285  struct _EqualElement {
286  template <class T>
287  inline bool operator()(T const &a, T const &b) const {
288  return a == b;
289  }
290  };
291 
292  friend struct Sdf_PathNodePrivateAccess;
293 
294  // Ref-counting ops manage _refCount.
295  friend void intrusive_ptr_add_ref(const Sdf_PathNode*);
296  friend void intrusive_ptr_release(const Sdf_PathNode*);
297 
298 private:
299  // Downcast helper, just sugar to static_cast this to Derived const *.
300  template <class Derived>
301  Derived const *_Downcast() const {
302  return static_cast<Derived const *>(this);
303  }
304 
305  // Helper to scan this node's name for the property namespace delimiter.
306  bool _IsNamespacedImpl() const;
307 
308  // Helper to return a const lvalue variant selection.
309  VariantSelectionType const &_GetEmptyVariantSelection() const;
310 
311  // Instance variables. PathNode's size is important to keep small. Please
312  // be mindful of that when making any changes here.
313  const Sdf_PathNodeConstRefPtr _parent;
314  mutable tbb::atomic<unsigned int> _refCount;
315 
316  const short _elementCount;
317  const unsigned char _nodeType;
318  const bool _isAbsolute:1;
319  const bool _containsPrimVariantSelection:1;
320  const bool _containsTargetPath:1;
321 
322  // This is racy -- we ensure that the token creation code carefully
323  // synchronizes so that if we read 'true' from this flag, it guarantees that
324  // there's a token for this path node in the token table. If we read
325  // 'false' it means there may or may not be, unless we're in the destructor,
326  // which must run exclusively, then reading 'false' guarantees there is no
327  // token in the table. We use this flag to do that optimization in the
328  // destructor so we can avoid looking in the table in the case where we
329  // haven't created a token.
330  mutable bool _hasToken:1;
331 };
332 
333 class Sdf_PrimPartPathNode : public Sdf_PathNode {
334 public:
335  using Sdf_PathNode::Sdf_PathNode;
336  SDF_API void operator delete (void *p);
337 };
338 
339 class Sdf_PropPartPathNode : public Sdf_PathNode {
340 public:
341  using Sdf_PathNode::Sdf_PathNode;
342  SDF_API void operator delete (void *p);
343 };
344 
345 class Sdf_RootPathNode : public Sdf_PrimPartPathNode {
346 public:
347  typedef bool ComparisonType;
348  static const NodeType nodeType = Sdf_PathNode::RootNode;
349 
350  static SDF_API Sdf_PathNode const *New(bool isAbsolute);
351 
352 private:
353  // This constructor is used only to create the two special root nodes.
354  Sdf_RootPathNode(bool isAbsolute) : Sdf_PrimPartPathNode(isAbsolute) {}
355 
356  ComparisonType _GetComparisonValue() const {
357  // Root nodes, there are only two, one absolute and one relative.
358  // (absolute < relative...)
359  return !IsAbsolutePath();
360  }
361 
362  friend class Sdf_PathNode;
363  template <int nodeType, class Comp> friend struct Sdf_PathNodeCompare;
364 };
365 
366 class Sdf_PrimPathNode : public Sdf_PrimPartPathNode {
367 public:
368  typedef TfToken ComparisonType;
369  static const NodeType nodeType = Sdf_PathNode::PrimNode;
370 
371 private:
372  Sdf_PrimPathNode(Sdf_PathNode const *parent,
373  const TfToken &name)
374  : Sdf_PrimPartPathNode(parent, nodeType)
375  , _name(name) {}
376 
377  SDF_API ~Sdf_PrimPathNode();
378 
379  const ComparisonType &_GetComparisonValue() const { return _name; }
380 
381  friend class Sdf_PathNode;
382  friend struct Sdf_PathNodePrivateAccess;
383  template <int nodeType, class Comp> friend struct Sdf_PathNodeCompare;
384 
385  // Instance variables
386  TfToken _name;
387 };
388 
389 class Sdf_PrimPropertyPathNode : public Sdf_PropPartPathNode {
390 public:
391  typedef TfToken ComparisonType;
392  static const NodeType nodeType = Sdf_PathNode::PrimPropertyNode;
393 
394 private:
395  Sdf_PrimPropertyPathNode(Sdf_PathNode const *parent,
396  const TfToken &name)
397  : Sdf_PropPartPathNode(parent, nodeType)
398  , _name(name) {}
399 
400  SDF_API ~Sdf_PrimPropertyPathNode();
401 
402  friend class Sdf_PathNode;
403  friend struct Sdf_PathNodePrivateAccess;
404  template <int nodeType, class Comp> friend struct Sdf_PathNodeCompare;
405 
406  const ComparisonType &_GetComparisonValue() const { return _name; }
407 
408  // Instance variables
409  TfToken _name;
410 };
411 
412 class Sdf_PrimVariantSelectionNode : public Sdf_PrimPartPathNode {
413 public:
414  typedef VariantSelectionType ComparisonType;
415  static const NodeType nodeType = Sdf_PathNode::PrimVariantSelectionNode;
416 
417  const TfToken &_GetNameImpl() const;
418 
419  template <class Buffer>
420  void _WriteTextImpl(Buffer &out) const;
421 
422 private:
423  Sdf_PrimVariantSelectionNode(Sdf_PathNode const *parent,
424  const VariantSelectionType &variantSelection)
425  : Sdf_PrimPartPathNode(parent, nodeType)
426  , _variantSelection(new VariantSelectionType(variantSelection)) {}
427 
428  SDF_API ~Sdf_PrimVariantSelectionNode();
429 
430  const ComparisonType &_GetComparisonValue() const {
431  return *_variantSelection;
432  }
433 
434  friend class Sdf_PathNode;
435  friend struct Sdf_PathNodePrivateAccess;
436  template <int nodeType, class Comp> friend struct Sdf_PathNodeCompare;
437 
438  // Instance variables
439  std::unique_ptr<VariantSelectionType> _variantSelection;
440 };
441 
442 class Sdf_TargetPathNode : public Sdf_PropPartPathNode {
443 public:
444  typedef SdfPath ComparisonType;
445  static const NodeType nodeType = Sdf_PathNode::TargetNode;
446 
447  template <class Buffer>
448  void _WriteTextImpl(Buffer &out) const;
449 
450 private:
451  Sdf_TargetPathNode(Sdf_PathNode const *parent,
452  const SdfPath &targetPath)
453  : Sdf_PropPartPathNode(parent, nodeType)
454  , _targetPath(targetPath) {}
455 
456  SDF_API ~Sdf_TargetPathNode();
457 
458  const ComparisonType& _GetComparisonValue() const { return _targetPath; }
459 
460  friend class Sdf_PathNode;
461  friend struct Sdf_PathNodePrivateAccess;
462  template <int nodeType, class Comp> friend struct Sdf_PathNodeCompare;
463 
464  // Instance variables
465  SdfPath _targetPath;
466 };
467 
468 class Sdf_RelationalAttributePathNode : public Sdf_PropPartPathNode {
469 public:
470  typedef TfToken ComparisonType;
471  static const NodeType nodeType = Sdf_PathNode::RelationalAttributeNode;
472 
473 private:
474  Sdf_RelationalAttributePathNode(Sdf_PathNode const *parent,
475  const TfToken &name)
476  : Sdf_PropPartPathNode(parent, nodeType)
477  , _name(name) {}
478 
479  SDF_API ~Sdf_RelationalAttributePathNode();
480 
481  const ComparisonType& _GetComparisonValue() const { return _name; }
482 
483  friend class Sdf_PathNode;
484  friend struct Sdf_PathNodePrivateAccess;
485  template <int nodeType, class Comp> friend struct Sdf_PathNodeCompare;
486 
487  // Instance variables
488  TfToken _name;
489 };
490 
491 class Sdf_MapperPathNode : public Sdf_PropPartPathNode {
492 public:
493  typedef SdfPath ComparisonType;
494  static const NodeType nodeType = Sdf_PathNode::MapperNode;
495 
496  template <class Buffer>
497  void _WriteTextImpl(Buffer &out) const;
498 
499 private:
500  Sdf_MapperPathNode(Sdf_PathNode const *parent,
501  const SdfPath &targetPath)
502  : Sdf_PropPartPathNode(parent, nodeType)
503  , _targetPath(targetPath) {}
504 
505  SDF_API ~Sdf_MapperPathNode();
506 
507  const ComparisonType& _GetComparisonValue() const { return _targetPath; }
508 
509  friend class Sdf_PathNode;
510  friend struct Sdf_PathNodePrivateAccess;
511  template <int nodeType, class Comp> friend struct Sdf_PathNodeCompare;
512 
513  // Instance variables
514  SdfPath _targetPath;
515 };
516 
517 class Sdf_MapperArgPathNode : public Sdf_PropPartPathNode {
518 public:
519  typedef TfToken ComparisonType;
520  static const NodeType nodeType = Sdf_PathNode::MapperArgNode;
521 
522  template <class Buffer>
523  void _WriteTextImpl(Buffer &out) const;
524 
525 private:
526  Sdf_MapperArgPathNode(Sdf_PathNode const *parent,
527  const TfToken &name)
528  : Sdf_PropPartPathNode(parent, nodeType)
529  , _name(name) {}
530 
531  SDF_API ~Sdf_MapperArgPathNode();
532 
533  const ComparisonType& _GetComparisonValue() const { return _name; }
534 
535  friend class Sdf_PathNode;
536  friend struct Sdf_PathNodePrivateAccess;
537  template <int nodeType, class Comp> friend struct Sdf_PathNodeCompare;
538 
539  // Instance variables
540  TfToken _name;
541 };
542 
543 class Sdf_ExpressionPathNode : public Sdf_PropPartPathNode {
544 public:
545  typedef void *ComparisonType;
546  static const NodeType nodeType = Sdf_PathNode::ExpressionNode;
547 
548  template <class Buffer>
549  void _WriteTextImpl(Buffer &out) const;
550 
551 private:
552  Sdf_ExpressionPathNode(Sdf_PathNode const *parent)
553  : Sdf_PropPartPathNode(parent, nodeType) {}
554 
555  SDF_API ~Sdf_ExpressionPathNode();
556 
557  ComparisonType _GetComparisonValue() const { return nullptr; }
558 
559  friend class Sdf_PathNode;
560  friend struct Sdf_PathNodePrivateAccess;
561  template <int nodeType, class Comp> friend struct Sdf_PathNodeCompare;
562 
563  // Instance variables
564  // <none>
565 };
566 
567 template <int nodeType>
568 struct Sdf_PathNodeTypeToType {
569 };
570 template <> struct Sdf_PathNodeTypeToType<Sdf_PathNode::PrimNode> {
571  typedef Sdf_PrimPathNode Type;
572 };
573 template <> struct Sdf_PathNodeTypeToType<Sdf_PathNode::PrimPropertyNode> {
574  typedef Sdf_PrimPropertyPathNode Type;
575 };
576 template <> struct Sdf_PathNodeTypeToType<Sdf_PathNode::RelationalAttributeNode> {
577  typedef Sdf_RelationalAttributePathNode Type;
578 };
579 template <> struct Sdf_PathNodeTypeToType<Sdf_PathNode::MapperArgNode> {
580  typedef Sdf_MapperArgPathNode Type;
581 };
582 template <> struct Sdf_PathNodeTypeToType<Sdf_PathNode::TargetNode> {
583  typedef Sdf_TargetPathNode Type;
584 };
585 template <> struct Sdf_PathNodeTypeToType<Sdf_PathNode::MapperNode> {
586  typedef Sdf_MapperPathNode Type;
587 };
588 template <> struct Sdf_PathNodeTypeToType<Sdf_PathNode::PrimVariantSelectionNode> {
589  typedef Sdf_PrimVariantSelectionNode Type;
590 };
591 template <> struct Sdf_PathNodeTypeToType<Sdf_PathNode::ExpressionNode> {
592  typedef Sdf_ExpressionPathNode Type;
593 };
594 template <> struct Sdf_PathNodeTypeToType<Sdf_PathNode::RootNode> {
595  typedef Sdf_RootPathNode Type;
596 };
597 
598 template <int nodeType, class Comp>
599 struct Sdf_PathNodeCompare {
600  inline bool operator()(const Sdf_PathNode &lhs,
601  const Sdf_PathNode &rhs) const {
602  typedef typename Sdf_PathNodeTypeToType<nodeType>::Type Type;
603  return Comp()(static_cast<const Type&>(lhs)._GetComparisonValue(),
604  static_cast<const Type&>(rhs)._GetComparisonValue());
605  }
606 };
607 
608 template <class Comp>
609 inline bool
610 Sdf_PathNode::Compare(const Sdf_PathNode &rhs) const
611 {
612  // Compare two nodes.
613  // We first compare types, then, if types match, we compare
614  // based on the type-specific content.
615  // Names are compared lexicographically.
616 
617  // Compare types. If node types are different use Comp() on them, otherwise
618  // continue to node-specific comparisons.
619 
620  NodeType nodeType = GetNodeType(), rhsNodeType = rhs.GetNodeType();
621  if (nodeType != rhsNodeType) {
622  return Comp()(nodeType, rhsNodeType);
623  }
624 
625  // Types are the same. Avoid virtual function calls for performance.
626  switch (nodeType) {
627  case Sdf_PathNode::PrimNode:
628  return Sdf_PathNodeCompare<Sdf_PathNode::PrimNode,
629  Comp>()(*this, rhs);
630  case Sdf_PathNode::PrimPropertyNode:
631  return Sdf_PathNodeCompare<Sdf_PathNode::PrimPropertyNode,
632  Comp>()(*this, rhs);
633  case Sdf_PathNode::RelationalAttributeNode:
634  return Sdf_PathNodeCompare<Sdf_PathNode::RelationalAttributeNode,
635  Comp>()(*this, rhs);
636  case Sdf_PathNode::MapperArgNode:
637  return Sdf_PathNodeCompare<Sdf_PathNode::MapperArgNode,
638  Comp>()(*this, rhs);
639  case Sdf_PathNode::TargetNode:
640  return Sdf_PathNodeCompare<Sdf_PathNode::TargetNode,
641  Comp>()(*this, rhs);
642  case Sdf_PathNode::MapperNode:
643  return Sdf_PathNodeCompare<Sdf_PathNode::MapperNode,
644  Comp>()(*this, rhs);
645  case Sdf_PathNode::PrimVariantSelectionNode:
646  return Sdf_PathNodeCompare<Sdf_PathNode::PrimVariantSelectionNode,
647  Comp>()(*this, rhs);
648  case Sdf_PathNode::ExpressionNode:
649  return Sdf_PathNodeCompare<Sdf_PathNode::ExpressionNode,
650  Comp>()(*this, rhs);
651  case Sdf_PathNode::RootNode:
652  return Sdf_PathNodeCompare<Sdf_PathNode::RootNode,
653  Comp>()(*this, rhs);
654  default:
655  TF_CODING_ERROR("Unhandled Sdf_PathNode::NodeType enumerant");
656  return false;
657  }
658 }
659 
660 inline void
661 Sdf_PathNode::_Destroy() const
662 {
663  // Note: This function deletes this object!
664  switch (_nodeType) {
665  case RootNode:
666  return delete _Downcast<Sdf_RootPathNode>();
667  case PrimNode:
668  return delete _Downcast<Sdf_PrimPathNode>();
669  case PrimPropertyNode:
670  return delete _Downcast<Sdf_PrimPropertyPathNode>();
671  case PrimVariantSelectionNode:
672  return delete _Downcast<Sdf_PrimVariantSelectionNode>();
673  case TargetNode:
674  return delete _Downcast<Sdf_TargetPathNode>();
675  case RelationalAttributeNode:
676  return delete _Downcast<Sdf_RelationalAttributePathNode>();
677  case MapperNode:
678  return delete _Downcast<Sdf_MapperPathNode>();
679  case MapperArgNode:
680  return delete _Downcast<Sdf_MapperArgPathNode>();
681  case ExpressionNode:
682  return delete _Downcast<Sdf_ExpressionPathNode>();
683  default:
684  return;
685  };
686 }
687 
688 inline const TfToken &
689 Sdf_PathNode::GetName() const
690 {
691  switch (_nodeType) {
692  default:
693  return SdfPathTokens->empty;
694  case RootNode:
695  return IsAbsolutePath() ?
696  SdfPathTokens->absoluteIndicator : SdfPathTokens->relativeRoot;
697  case PrimNode:
698  return _Downcast<Sdf_PrimPathNode>()->_name;
699  case PrimPropertyNode:
700  return _Downcast<Sdf_PrimPropertyPathNode>()->_name;
701  case PrimVariantSelectionNode:
702  return _Downcast<Sdf_PrimVariantSelectionNode>()->_GetNameImpl();
703  case RelationalAttributeNode:
704  return _Downcast<Sdf_RelationalAttributePathNode>()->_name;
705  case MapperArgNode:
706  return _Downcast<Sdf_MapperArgPathNode>()->_name;
707  case ExpressionNode:
708  return SdfPathTokens->expressionIndicator;
709  }
710 }
711 
712 inline const SdfPath &
713 Sdf_PathNode::GetTargetPath() const
714 {
715  switch (_nodeType) {
716  default:
717  return SdfPath::EmptyPath();
718  case TargetNode:
719  return _Downcast<Sdf_TargetPathNode>()->_targetPath;
720  case MapperNode:
721  return _Downcast<Sdf_MapperPathNode>()->_targetPath;
722  };
723 }
724 
725 inline const Sdf_PathNode::VariantSelectionType &
726 Sdf_PathNode::GetVariantSelection() const
727 {
728  if (ARCH_LIKELY(_nodeType == PrimVariantSelectionNode)) {
729  return *_Downcast<Sdf_PrimVariantSelectionNode>()->_variantSelection;
730  }
731  return _GetEmptyVariantSelection();
732 }
733 
734 inline TfToken
735 Sdf_PathNode::GetElement() const
736 {
737  switch (_nodeType) {
738  case RootNode:
739  return TfToken();
740  case PrimNode:
741  return _Downcast<Sdf_PrimPathNode>()->_name;
742  default:
743  return _GetElementImpl();
744  };
745 }
746 
748 SDF_API void Sdf_DumpPathStats();
749 
750 inline void intrusive_ptr_add_ref(const PXR_NS::Sdf_PathNode* p) {
751  ++p->_refCount;
752 }
753 inline void intrusive_ptr_release(const PXR_NS::Sdf_PathNode* p) {
754  if (p->_refCount.fetch_and_decrement() == 1)
755  p->_Destroy();
756 }
757 
758 PXR_NAMESPACE_CLOSE_SCOPE
759 
760 #endif // PXR_USD_SDF_PATH_NODE_H
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:85
This class provides a non-owning reference to a type-erased callable object with a specified signatur...
Definition: functionRef.h:36
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:87
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:290
static SDF_API const SdfPath & EmptyPath()
The empty path value, equivalent to SdfPath().
TfToken class for efficient string referencing and hashing, plus conversions to and from stl string c...