HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
path.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_USD_SDF_PATH_H
8 #define PXR_USD_SDF_PATH_H
9 
10 #include "pxr/pxr.h"
11 #include "pxr/usd/sdf/api.h"
12 #include "pxr/usd/sdf/pool.h"
13 #include "pxr/usd/sdf/tokens.h"
14 #include "pxr/base/arch/defines.h"
16 #include "pxr/base/tf/span.h"
17 #include "pxr/base/tf/stl.h"
18 #include "pxr/base/tf/token.h"
19 #include "pxr/base/vt/traits.h"
20 
21 #include <algorithm>
22 #include <iterator>
23 #include <set>
24 #include <string>
25 #include <type_traits>
26 #include <utility>
27 #include <vector>
28 
30 
31 class Sdf_PathNode;
33 
34 // Ref-counting pointer to a path node.
35 // Delegated ref-counts are used to keep the size of SdfPath
36 // the same as a raw pointer. (shared_ptr, by comparison,
37 // is the size of two pointers.)
38 
40 
41 void TfDelegatedCountIncrement(Sdf_PathNode const *) noexcept;
42 void TfDelegatedCountDecrement(Sdf_PathNode const *) noexcept;
43 
44 // Tags used for the pools of path nodes.
45 struct Sdf_PathPrimTag;
46 struct Sdf_PathPropTag;
47 
48 
49 // The sizes below represent the largest sizes of the prim and property
50 // Sdf_PathNode subclasses.
51 #ifdef ARCH_BITS_32
52 static constexpr size_t Sdf_MaxSizeofPrimPathNode = 16;
53 static constexpr size_t Sdf_MaxSizeofPropPathNode = 20;
54 #else
55 static constexpr size_t Sdf_MaxSizeofPrimPathNode = 24;
56 static constexpr size_t Sdf_MaxSizeofPropPathNode = 24;
57 #endif
58 
60  Sdf_PathPrimTag, Sdf_MaxSizeofPrimPathNode, /*regionBits=*/8>;
61 
63  Sdf_PathPropTag, Sdf_MaxSizeofPropPathNode, /*regionBits=*/8>;
64 
67 
68 // This handle class wraps up the raw Prim/PropPartPool handles.
69 template <class Handle, bool Counted, class PathNode=Sdf_PathNode const>
71 private:
73 
74 public:
75  static constexpr bool IsCounted = Counted;
76 
77  constexpr Sdf_PathNodeHandleImpl() noexcept {};
78 
79  explicit
80  Sdf_PathNodeHandleImpl(Sdf_PathNode const *p, bool add_ref = true)
81  : _poolHandle(Handle::GetHandle(reinterpret_cast<char const *>(p))) {
82  if (p && add_ref) {
83  _AddRef(p);
84  }
85  }
86 
87  explicit
88  Sdf_PathNodeHandleImpl(Handle h, bool add_ref = true)
89  : _poolHandle(h) {
90  if (h && add_ref) {
91  _AddRef();
92  }
93  }
94 
96  : _poolHandle(rhs._poolHandle) {
97  if (_poolHandle) {
98  _AddRef();
99  }
100  }
101 
103  if (_poolHandle) {
104  _DecRef();
105  }
106  }
107 
110  if (Counted && *this == rhs) {
111  return *this;
112  }
113  this_type(rhs).swap(*this);
114  return *this;
115  }
116 
118  : _poolHandle(rhs._poolHandle) {
119  rhs._poolHandle = nullptr;
120  }
121 
124  this_type(std::move(rhs)).swap(*this);
125  return *this;
126  }
127 
129  operator=(Sdf_PathNode const *rhs) noexcept {
130  this_type(rhs).swap(*this);
131  return *this;
132  }
133 
134  void reset() noexcept {
135  _poolHandle = Handle { nullptr };
136  }
137 
138  inline Sdf_PathNode const *
139  get() const noexcept {
140  return reinterpret_cast<Sdf_PathNode *>(_poolHandle.GetPtr());
141  }
142 
143  Sdf_PathNode const &
144  operator*() const {
145  return *get();
146  }
147 
148  Sdf_PathNode const *
149  operator->() const {
150  return get();
151  }
152 
153  explicit operator bool() const noexcept {
154  return static_cast<bool>(_poolHandle);
155  }
156 
157  void swap(Sdf_PathNodeHandleImpl &rhs) noexcept {
158  _poolHandle.swap(rhs._poolHandle);
159  }
160 
161  inline bool operator==(Sdf_PathNodeHandleImpl const &rhs) const noexcept {
162  return _poolHandle == rhs._poolHandle;
163  }
164  inline bool operator!=(Sdf_PathNodeHandleImpl const &rhs) const noexcept {
165  return _poolHandle != rhs._poolHandle;
166  }
167  inline bool operator<(Sdf_PathNodeHandleImpl const &rhs) const noexcept {
168  return _poolHandle < rhs._poolHandle;
169  }
170 private:
171 
172  inline void _AddRef(Sdf_PathNode const *p) const {
173  if (Counted) {
175  }
176  }
177 
178  inline void _AddRef() const {
179  _AddRef(get());
180  }
181 
182  inline void _DecRef() const {
183  if (Counted) {
185  }
186  }
187 
188  Handle _poolHandle { nullptr };
189 };
190 
193 
196 
197 
198 /// A set of SdfPaths.
199 typedef std::set<class SdfPath> SdfPathSet;
200 /// A vector of SdfPaths.
201 typedef std::vector<class SdfPath> SdfPathVector;
202 
203 // Tell VtValue that SdfPath is cheap to copy.
205 
206 /// \class SdfPath
207 ///
208 /// A path value used to locate objects in layers or scenegraphs.
209 ///
210 /// \section sec_SdfPath_Overview Overview
211 ///
212 /// SdfPath is used in several ways:
213 /// \li As a storage key for addressing and accessing values held in a SdfLayer
214 /// \li As a namespace identity for scenegraph objects
215 /// \li As a way to refer to other scenegraph objects through relative paths
216 ///
217 /// The paths represented by an SdfPath class may be either relative or
218 /// absolute. Relative paths are relative to the prim object that contains them
219 /// (that is, if an SdfRelationshipSpec target is relative, it is relative to
220 /// the SdfPrimSpec object that owns the SdfRelationshipSpec object).
221 ///
222 /// SdfPath objects can be readily created from and converted back to strings,
223 /// but as SdfPath objects, they have behaviors that make it easy and efficient
224 /// to work with them. The SdfPath class provides a full range of methods for
225 /// manipulating scene paths by appending a namespace child, appending a
226 /// relationship target, getting the parent path,
227 /// and so on. Since the SdfPath class uses a node-based representation
228 /// internally, you should use the editing functions rather than converting to
229 /// and from strings if possible.
230 ///
231 /// \section sec_SdfPath_Syntax Path Syntax
232 ///
233 /// Like a filesystem path, an SdfPath is conceptually just a sequence of
234 /// path components. Unlike a filesystem path, each component has a type,
235 /// and the type is indicated by the syntax.
236 ///
237 /// Two separators are used between parts of a path. A slash ("/") following an
238 /// identifier is used to introduce a namespace child. A period (".") following
239 /// an identifier is used to introduce a property. A property may also have
240 /// several non-sequential colons (':') in its name to provide a rudimentary
241 /// namespace within properties but may not end or begin with a colon.
242 ///
243 /// A leading slash in the string representation of an SdfPath object indicates
244 /// an absolute path. Two adjacent periods indicate the parent namespace.
245 ///
246 /// Brackets ("[" and "]") are used to indicate relationship target paths for
247 /// relational attributes.
248 ///
249 /// The first part in a path is assumed to be a namespace child unless
250 /// it is preceded by a period. That means:
251 /// \li <c>/Foo</c> is an absolute path specifying the root prim Foo.
252 /// \li <c>/Foo/Bar</c> is an absolute path specifying namespace child Bar
253 /// of root prim Foo.
254 /// \li <c>/Foo/Bar.baz</c> is an absolute path specifying property \c baz of
255 /// namespace child Bar of root prim Foo.
256 /// \li <c>Foo</c> is a relative path specifying namespace child Foo of
257 /// the current prim.
258 /// \li <c>Foo/Bar</c> is a relative path specifying namespace child Bar of
259 /// namespace child Foo of the current prim.
260 /// \li <c>Foo/Bar.baz</c> is a relative path specifying property \c baz of
261 /// namespace child Bar of namespace child Foo of the current prim.
262 /// \li <c>.foo</c> is a relative path specifying the property \c foo of the
263 /// current prim.
264 /// \li <c>/Foo.bar[/Foo.baz].attrib</c> is a relational attribute path. The
265 /// relationship <c>/Foo.bar</c> has a target <c>/Foo.baz</c>. There is a
266 /// relational attribute \c attrib on that relationship-&gt;target pair.
267 ///
268 /// \section sec_SdfPath_ThreadSafety A Note on Thread-Safety
269 ///
270 /// SdfPath is strongly thread-safe, in the sense that zero additional
271 /// synchronization is required between threads creating or using SdfPath
272 /// values. Just like TfToken, SdfPath values are immutable. Internally,
273 /// SdfPath uses a global prefix tree to efficiently share representations
274 /// of paths, and provide fast equality/hashing operations, but
275 /// modifications to this table are internally synchronized. Consequently,
276 /// as with TfToken, for best performance it is important to minimize
277 /// the number of values created (since it requires synchronized access to
278 /// this table) or copied (since it requires atomic ref-counting operations).
279 ///
280 class SdfPath
281 {
282 public:
283  /// The empty path value, equivalent to SdfPath().
284  SDF_API static const SdfPath & EmptyPath();
285 
286  /// The absolute path representing the top of the
287  /// namespace hierarchy.
288  SDF_API static const SdfPath & AbsoluteRootPath();
289 
290  /// The relative path representing "self".
291  SDF_API static const SdfPath & ReflexiveRelativePath();
292 
293  /// \name Constructors
294  /// @{
295 
296  /// Constructs the default, empty path.
297  ///
298  SdfPath() noexcept = default;
299 
300  /// Creates a path from the given string.
301  ///
302  /// If the given string is not a well-formed path, this will raise
303  /// a Tf error. Note that passing an empty std::string() will also
304  /// raise an error; the correct way to get the empty path is SdfPath().
305  ///
306  /// Internal dot-dots will be resolved by removing the first dot-dot,
307  /// the element preceding it, and repeating until no internal dot-dots
308  /// remain.
309  ///
310  /// Note that most often new paths are expected to be created by
311  /// asking existing paths to return modified versions of themselves.
312  //
313  // XXX We may want to revisit the behavior when constructing
314  // a path with an empty string ("") to accept it without error and
315  // return EmptyPath.
316  SDF_API explicit SdfPath(const std::string &path);
317 
318  /// @}
319 
320  /// \name Querying paths
321  /// @{
322 
323  /// Returns the number of path elements in this path.
324  SDF_API size_t GetPathElementCount() const;
325 
326  /// Returns whether the path is absolute.
327  SDF_API bool IsAbsolutePath() const;
328 
329  /// Return true if this path is the AbsoluteRootPath().
330  SDF_API bool IsAbsoluteRootPath() const;
331 
332  /// Returns whether the path identifies a prim.
333  SDF_API bool IsPrimPath() const;
334 
335  /// Returns whether the path identifies a prim or the absolute root.
336  SDF_API bool IsAbsoluteRootOrPrimPath() const;
337 
338  /// Returns whether the path identifies a root prim.
339  ///
340  /// the path must be absolute and have a single element
341  /// (for example <c>/foo</c>).
342  SDF_API bool IsRootPrimPath() const;
343 
344  /// Returns whether the path identifies a property.
345  ///
346  /// A relational attribute is considered to be a property, so this
347  /// method will return true for relational attributes as well
348  /// as properties of prims.
349  SDF_API bool IsPropertyPath() const;
350 
351  /// Returns whether the path identifies a prim's property.
352  ///
353  /// A relational attribute is not a prim property.
354  SDF_API bool IsPrimPropertyPath() const;
355 
356  /// Returns whether the path identifies a namespaced property.
357  ///
358  /// A namespaced property has colon embedded in its name.
359  SDF_API bool IsNamespacedPropertyPath() const;
360 
361  /// Returns whether the path identifies a variant selection for a
362  /// prim.
363  SDF_API bool IsPrimVariantSelectionPath() const;
364 
365  /// Return true if this path is a prim path or is a prim variant
366  /// selection path.
368 
369  /// Returns whether the path or any of its parent paths identifies
370  /// a variant selection for a prim.
372 
373  /// Return true if this path contains any property elements, false
374  /// otherwise. A false return indicates a prim-like path, specifically a
375  /// root path, a prim path, or a prim variant selection path. A true return
376  /// indicates a property-like path: a prim property path, a target path, a
377  /// relational attribute path, etc.
379  return static_cast<bool>(_propPart);
380  }
381 
382  /// Return true if this path is or has a prefix that's a target path or a
383  /// mapper path.
384  SDF_API bool ContainsTargetPath() const;
385 
386  /// Returns whether the path identifies a relational attribute.
387  ///
388  /// If this is true, IsPropertyPath() will also be true.
389  SDF_API bool IsRelationalAttributePath() const;
390 
391  /// Returns whether the path identifies a relationship or
392  /// connection target.
393  SDF_API bool IsTargetPath() const;
394 
395  /// Returns whether the path identifies a connection mapper.
396  SDF_API bool IsMapperPath() const;
397 
398  /// Returns whether the path identifies a connection mapper arg.
399  SDF_API bool IsMapperArgPath() const;
400 
401  /// Returns whether the path identifies a connection expression.
402  SDF_API bool IsExpressionPath() const;
403 
404  /// Returns true if this is the empty path (SdfPath::EmptyPath()).
405  inline bool IsEmpty() const noexcept {
406  // No need to check _propPart, because it can only be non-null if
407  // _primPart is non-null.
408  return !_primPart;
409  }
410 
411  /// Return the string representation of this path as a TfToken.
412  ///
413  /// This function is recommended only for human-readable or diagnostic
414  /// output. Use the SdfPath API to manipulate paths. It is less
415  /// error-prone and has better performance.
416  SDF_API TfToken GetAsToken() const;
417 
418  /// Return the string representation of this path as a TfToken lvalue.
419  ///
420  /// This function returns a persistent lvalue. If an rvalue will suffice,
421  /// call GetAsToken() instead. That avoids populating internal data
422  /// structures to hold the persistent token.
423  ///
424  /// This function is recommended only for human-readable or diagnostic
425  /// output. Use the SdfPath API to manipulate paths. It is less
426  /// error-prone and has better performance.
427  SDF_API TfToken const &GetToken() const;
428 
429  /// Return the string representation of this path as a std::string.
430  ///
431  /// This function is recommended only for human-readable or diagnostic
432  /// output. Use the SdfPath API to manipulate paths. It is less
433  /// error-prone and has better performance.
434  SDF_API std::string GetAsString() const;
435 
436  /// Return the string representation of this path as a std::string.
437  ///
438  /// This function returns a persistent lvalue. If an rvalue will suffice,
439  /// call GetAsString() instead. That avoids populating internal data
440  /// structures to hold the persistent string.
441  ///
442  /// This function is recommended only for human-readable or diagnostic
443  /// output. Use the SdfPath API to manipulate paths. It is less
444  /// error-prone and has better performance.
445  SDF_API const std::string &GetString() const;
446 
447  /// Returns the string representation of this path as a c string.
448  ///
449  /// This function returns a pointer to a persistent c string. If a
450  /// temporary c string will suffice, call GetAsString().c_str() instead.
451  /// That avoids populating internal data structures to hold the persistent
452  /// string.
453  ///
454  /// This function is recommended only for human-readable or diagnostic
455  /// output. Use the SdfPath API to manipulate paths. It is less
456  /// error-prone and has better performance.
457  SDF_API const char *GetText() const;
458 
459  /// Returns the prefix paths of this path.
460  ///
461  /// Prefixes are returned in order of shortest to longest. The path
462  /// itself is returned as the last prefix.
463  /// Note that if the prefix order does not need to be from shortest to
464  /// longest, it is more efficient to use GetAncestorsRange, which
465  /// produces an equivalent set of paths, ordered from longest to shortest.
466  SDF_API SdfPathVector GetPrefixes() const;
467 
468  /// Return up to \p numPrefixes prefix paths of this path.
469  ///
470  /// Prefixes are returned in order of shortest to longest. The path itself
471  /// is returned as the last prefix. Note that if the prefix order does not
472  /// need to be from shortest to longest, it is more efficient to use
473  /// GetAncestorsRange, which produces an equivalent set of paths, ordered
474  /// from longest to shortest. If \p numPrefixes is 0 or greater than the
475  /// number of this path's prefixes, fill all prefixes.
476  SDF_API SdfPathVector GetPrefixes(size_t numPrefixes) const;
477 
478  /// Fills prefixes with prefixes of this path.
479  ///
480  /// This avoids copy constructing the return value.
481  ///
482  /// Prefixes are returned in order of shortest to longest. The path
483  /// itself is returned as the last prefix.
484  /// Note that if the prefix order does not need to be from shortest to
485  /// longest, it is more efficient to use GetAncestorsRange(), which
486  /// produces an equivalent set of paths, ordered from longest to shortest.
487  SDF_API void GetPrefixes(SdfPathVector *prefixes) const;
488 
489  /// Fill \p prefixes with up to \p numPrefixes prefixes of this path.
490  ///
491  /// Prefixes are filled in order of shortest to longest. The path itself is
492  /// included as the last prefix. Note that if the prefix order does not
493  /// need to be from shortest to longest, it can be more efficient to use
494  /// GetAncestorsRange(), which produces an equivalent set of paths, ordered
495  /// from longest to shortest. If \p numPrefixes is 0 or greater than the
496  /// number of this path's prefixes, fill all prefixes.
497  SDF_API void GetPrefixes(SdfPathVector *prefixes, size_t numPrefixes) const;
498 
499  /// Fill \p prefixes with up to \p prefixes.size() prefixes of this path.
500  /// Return the subspan of prefixes filled.
501  ///
502  /// Prefixes are filled in order of shortest to longest. The path itself is
503  /// always included as the last prefix. If \p prefixes is not large enough
504  /// to contain all prefixes, the shortest prefixes are omitted. If \p
505  /// prefixes is larger than the number of prefixes filled, return the
506  /// subspan filled by calling TfSpan::first() with the number of filled
507  /// prefixes. Note that if the prefix order does not need to be from
508  /// shortest to longest, it can be more efficient to use
509  /// GetAncestorsRange(), which produces an equivalent set of paths, ordered
510  /// from longest to shortest.
512 
513  /// Return a range for iterating over the ancestors of this path.
514  ///
515  /// The range provides iteration over the path and all of its prefixes,
516  /// ordered from longest to shortest (the opposite of the order of the
517  /// prefixes returned by GetPrefixes(). For example, given a path like
518  /// `/a/b.prop`, the range would contain `/a/b.prop`, `/a/b` and `/a`, in
519  /// that order.
521 
522  /// Returns the name of the prim, property or relational
523  /// attribute identified by the path.
524  ///
525  /// Returns EmptyPath if this path is a target or mapper path.
526  ///
527  /// <ul>
528  /// <li>Returns "" for EmptyPath.</li>
529  /// <li>Returns "." for ReflexiveRelativePath.</li>
530  /// <li>Returns ".." for a path ending in ParentPathElement.</li>
531  /// </ul>
532  SDF_API const std::string &GetName() const;
533 
534  /// Returns the name of the prim, property or relational
535  /// attribute identified by the path, as a token.
536  SDF_API const TfToken &GetNameToken() const;
537 
538  /// Returns an ascii representation of the "terminal" element
539  /// of this path, which can be used to reconstruct the path using
540  /// \c AppendElementString() on its parent.
541  ///
542  /// EmptyPath(), AbsoluteRootPath(), and ReflexiveRelativePath() are
543  /// \em not considered elements (one of the defining properties of
544  /// elements is that they have a parent), so \c GetElementString() will
545  /// return the empty string for these paths.
546  ///
547  /// Unlike \c GetName() and \c GetTargetPath(), which provide you "some"
548  /// information about the terminal element, this provides a complete
549  /// representation of the element, for all element types.
550  ///
551  /// Also note that whereas \c GetName(), \c GetNameToken(), \c GetText(),
552  /// \c GetString(), and \c GetTargetPath() return cached results,
553  /// \c GetElementString() always performs some amount of string
554  /// manipulation, which you should keep in mind if performance is a concern.
555  SDF_API std::string GetElementString() const;
556 
557  /// Like GetElementString() but return the value as a TfToken.
559 
560  /// Return a copy of this path with its final component changed to
561  /// \a newName. This path must be a prim or property path.
562  ///
563  /// This method is shorthand for path.GetParentPath().AppendChild(newName)
564  /// for prim paths, path.GetParentPath().AppendProperty(newName) for
565  /// prim property paths, and
566  /// path.GetParentPath().AppendRelationalAttribute(newName) for relational
567  /// attribute paths.
568  ///
569  /// Note that only the final path component is ever changed. If the name of
570  /// the final path component appears elsewhere in the path, it will not be
571  /// modified.
572  ///
573  /// Some examples:
574  ///
575  /// ReplaceName('/chars/MeridaGroup', 'AngusGroup') -> '/chars/AngusGroup'
576  /// ReplaceName('/Merida.tx', 'ty') -> '/Merida.ty'
577  /// ReplaceName('/Merida.tx[targ].tx', 'ty') -> '/Merida.tx[targ].ty'
578  ///
579  SDF_API SdfPath ReplaceName(TfToken const &newName) const;
580 
581  /// Returns the relational attribute or mapper target path
582  /// for this path.
583  ///
584  /// Returns EmptyPath if this is not a target, relational attribute or
585  /// mapper path.
586  ///
587  /// Note that it is possible for a path to have multiple "target" paths.
588  /// For example a path that identifies a connection target for a
589  /// relational attribute includes the target of the connection as well
590  /// as the target of the relational attribute. In these cases, the
591  /// "deepest" or right-most target path will be returned (the connection
592  /// target in this example).
593  SDF_API const SdfPath &GetTargetPath() const;
594 
595  /// Returns all the relationship target or connection target
596  /// paths contained in this path, and recursively all the target paths
597  /// contained in those target paths in reverse depth-first order.
598  ///
599  /// For example, given the path: '/A/B.a[/C/D.a[/E/F.a]].a[/A/B.a[/C/D.a]]'
600  /// this method produces: '/A/B.a[/C/D.a]', '/C/D.a', '/C/D.a[/E/F.a]',
601  /// '/E/F.a'
602  SDF_API void GetAllTargetPathsRecursively(SdfPathVector *result) const;
603 
604  /// Returns the variant selection for this path, if this is a variant
605  /// selection path.
606  /// Returns a pair of empty strings if this path is not a variant
607  /// selection path.
608  SDF_API
609  std::pair<std::string, std::string> GetVariantSelection() const;
610 
611  /// Return true if both this path and \a prefix are not the empty
612  /// path and this path has \a prefix as a prefix. Return false otherwise.
613  SDF_API bool HasPrefix( const SdfPath &prefix ) const;
614 
615  /// @}
616 
617  /// \name Creating new paths by modifying existing paths
618  /// @{
619 
620  /// Return the path that identifies this path's namespace parent.
621  ///
622  /// For a prim path (like '/foo/bar'), return the prim's parent's path
623  /// ('/foo'). For a prim property path (like '/foo/bar.property'), return
624  /// the prim's path ('/foo/bar'). For a target path (like
625  /// '/foo/bar.property[/target]') return the property path
626  /// ('/foo/bar.property'). For a mapper path (like
627  /// '/foo/bar.property.mapper[/target]') return the property path
628  /// ('/foo/bar.property). For a relational attribute path (like
629  /// '/foo/bar.property[/target].relAttr') return the relationship target's
630  /// path ('/foo/bar.property[/target]'). For a prim variant selection path
631  /// (like '/foo/bar{var=sel}') return the prim path ('/foo/bar'). For a
632  /// root prim path (like '/rootPrim'), return AbsoluteRootPath() ('/'). For
633  /// a single element relative prim path (like 'relativePrim'), return
634  /// ReflexiveRelativePath() ('.'). For ReflexiveRelativePath(), return the
635  /// relative parent path ('..').
636  ///
637  /// Note that the parent path of a relative parent path ('..') is a relative
638  /// grandparent path ('../..'). Use caution writing loops that walk to
639  /// parent paths since relative paths have infinitely many ancestors. To
640  /// more safely traverse ancestor paths, consider iterating over an
641  /// SdfPathAncestorsRange instead, as returned by GetAncestorsRange().
642  SDF_API SdfPath GetParentPath() const;
643 
644  /// Creates a path by stripping all relational attributes, targets,
645  /// properties, and variant selections from the leafmost prim path, leaving
646  /// the nearest path for which \a IsPrimPath() returns true.
647  ///
648  /// See \a GetPrimOrPrimVariantSelectionPath also.
649  ///
650  /// If the path is already a prim path, the same path is returned.
651  SDF_API SdfPath GetPrimPath() const;
652 
653  /// Creates a path by stripping all relational attributes, targets,
654  /// and properties, leaving the nearest path for which
655  /// \a IsPrimOrPrimVariantSelectionPath() returns true.
656  ///
657  /// See \a GetPrimPath also.
658  ///
659  /// If the path is already a prim or a prim variant selection path, the same
660  /// path is returned.
662 
663  /// Creates a path by stripping all properties and relational
664  /// attributes from this path, leaving the path to the containing prim.
665  ///
666  /// If the path is already a prim or absolute root path, the same
667  /// path is returned.
668  SDF_API SdfPath GetAbsoluteRootOrPrimPath() const;
669 
670  /// Create a path by stripping all variant selections from all
671  /// components of this path, leaving a path with no embedded variant
672  /// selections.
673  SDF_API SdfPath StripAllVariantSelections() const;
674 
675  /// Creates a path by appending a given relative path to this path.
676  ///
677  /// If the newSuffix is a prim path, then this path must be a prim path
678  /// or a root path.
679  ///
680  /// If the newSuffix is a prim property path, then this path must be
681  /// a prim path or the ReflexiveRelativePath.
682  SDF_API SdfPath AppendPath(const SdfPath &newSuffix) const;
683 
684  /// Creates a path by appending an element for \p childName
685  /// to this path.
686  ///
687  /// This path must be a prim path, the AbsoluteRootPath
688  /// or the ReflexiveRelativePath.
689  SDF_API SdfPath AppendChild(TfToken const &childName) const;
690 
691  /// Creates a path by appending an element for \p propName
692  /// to this path.
693  ///
694  /// This path must be a prim path or the ReflexiveRelativePath.
695  SDF_API SdfPath AppendProperty(TfToken const &propName) const;
696 
697  /// Creates a path by appending an element for \p variantSet
698  /// and \p variant to this path.
699  ///
700  /// This path must be a prim path.
701  SDF_API
702  SdfPath AppendVariantSelection(const std::string &variantSet,
703  const std::string &variant) const;
704 
705  /// Creates a path by appending an element for
706  /// \p targetPath.
707  ///
708  /// This path must be a prim property or relational attribute path.
709  SDF_API SdfPath AppendTarget(const SdfPath &targetPath) const;
710 
711  /// Creates a path by appending an element for
712  /// \p attrName to this path.
713  ///
714  /// This path must be a target path.
715  SDF_API
716  SdfPath AppendRelationalAttribute(TfToken const &attrName) const;
717 
718  /// Replaces the relational attribute's target path
719  ///
720  /// The path must be a relational attribute path.
721  SDF_API
722  SdfPath ReplaceTargetPath( const SdfPath &newTargetPath ) const;
723 
724  /// Creates a path by appending a mapper element for
725  /// \p targetPath.
726  ///
727  /// This path must be a prim property or relational attribute path.
728  SDF_API SdfPath AppendMapper(const SdfPath &targetPath) const;
729 
730  /// Creates a path by appending an element for
731  /// \p argName.
732  ///
733  /// This path must be a mapper path.
734  SDF_API SdfPath AppendMapperArg(TfToken const &argName) const;
735 
736  /// Creates a path by appending an expression element.
737  ///
738  /// This path must be a prim property or relational attribute path.
739  SDF_API SdfPath AppendExpression() const;
740 
741  /// Creates a path by extracting and appending an element
742  /// from the given ascii element encoding.
743  ///
744  /// Attempting to append a root or empty path (or malformed path)
745  /// or attempting to append \em to the EmptyPath will raise an
746  /// error and return the EmptyPath.
747  ///
748  /// May also fail and return EmptyPath if this path's type cannot
749  /// possess a child of the type encoded in \p element.
750  SDF_API SdfPath AppendElementString(const std::string &element) const;
751 
752  /// Like AppendElementString() but take the element as a TfToken.
753  SDF_API SdfPath AppendElementToken(const TfToken &elementTok) const;
754 
755  /// Returns a path with all occurrences of the prefix path
756  /// \p oldPrefix replaced with the prefix path \p newPrefix.
757  ///
758  /// If fixTargetPaths is true, any embedded target paths will also
759  /// have their paths replaced. This is the default.
760  ///
761  /// If this is not a target, relational attribute or mapper path this
762  /// will do zero or one path prefix replacements, if not the number of
763  /// replacements can be greater than one.
764  SDF_API
765  SdfPath ReplacePrefix(const SdfPath &oldPrefix,
766  const SdfPath &newPrefix,
767  bool fixTargetPaths=true) const;
768 
769  /// Returns a path with maximal length that is a prefix path of
770  /// both this path and \p path.
771  SDF_API SdfPath GetCommonPrefix(const SdfPath &path) const;
772 
773  /// Find and remove the longest common suffix from two paths.
774  ///
775  /// Returns this path and \p otherPath with the longest common suffix
776  /// removed (first and second, respectively). If the two paths have no
777  /// common suffix then the paths are returned as-is. If the paths are
778  /// equal then this returns empty paths for relative paths and absolute
779  /// roots for absolute paths. The paths need not be the same length.
780  ///
781  /// If \p stopAtRootPrim is \c true then neither returned path will be
782  /// the root path. That, in turn, means that some common suffixes will
783  /// not be removed. For example, if \p stopAtRootPrim is \c true then
784  /// the paths /A/B and /B will be returned as is. Were it \c false
785  /// then the result would be /A and /. Similarly paths /A/B/C and
786  /// /B/C would return /A/B and /B if \p stopAtRootPrim is \c true but
787  /// /A and / if it's \c false.
788  SDF_API
789  std::pair<SdfPath, SdfPath>
790  RemoveCommonSuffix(const SdfPath& otherPath,
791  bool stopAtRootPrim = false) const;
792 
793  /// Returns the absolute form of this path using \p anchor
794  /// as the relative basis.
795  ///
796  /// \p anchor must be an absolute prim path.
797  ///
798  /// If this path is a relative path, resolve it using \p anchor as the
799  /// relative basis.
800  ///
801  /// If this path is already an absolute path, just return a copy.
802  SDF_API SdfPath MakeAbsolutePath(const SdfPath & anchor) const;
803 
804  /// Returns the relative form of this path using \p anchor
805  /// as the relative basis.
806  ///
807  /// \p anchor must be an absolute prim path.
808  ///
809  /// If this path is an absolute path, return the corresponding relative path
810  /// that is relative to the absolute path given by \p anchor.
811  ///
812  /// If this path is a relative path, return the optimal relative
813  /// path to the absolute path given by \p anchor. (The optimal
814  /// relative path from a given prim path is the relative path
815  /// with the least leading dot-dots.
816  SDF_API SdfPath MakeRelativePath(const SdfPath & anchor) const;
817 
818  /// @}
819 
820  /// \name Valid path strings, prim and property names
821  /// @{
822 
823  /// Returns whether \p name is a legal identifier for any
824  /// path component.
825  SDF_API static bool IsValidIdentifier(const std::string &name);
826 
827  /// Returns whether \p name is a legal namespaced identifier.
828  /// This returns \c true if IsValidIdentifier() does.
829  SDF_API static bool IsValidNamespacedIdentifier(const std::string &name);
830 
831  /// Tokenizes \p name by the namespace delimiter.
832  /// Returns the empty vector if \p name is not a valid namespaced
833  /// identifier.
834  SDF_API static std::vector<std::string> TokenizeIdentifier(const std::string &name);
835 
836  /// Tokenizes \p name by the namespace delimiter.
837  /// Returns the empty vector if \p name is not a valid namespaced
838  /// identifier.
839  SDF_API
840  static TfTokenVector TokenizeIdentifierAsTokens(const std::string &name);
841 
842  /// Join \p names into a single identifier using the namespace delimiter.
843  /// Any empty strings present in \p names are ignored when joining.
844  SDF_API
845  static std::string JoinIdentifier(const std::vector<std::string> &names);
846 
847  /// Join \p names into a single identifier using the namespace delimiter.
848  /// Any empty strings present in \p names are ignored when joining.
849  SDF_API
850  static std::string JoinIdentifier(const TfTokenVector& names);
851 
852  /// Join \p lhs and \p rhs into a single identifier using the
853  /// namespace delimiter.
854  /// Returns \p lhs if \p rhs is empty and vice verse.
855  /// Returns an empty string if both \p lhs and \p rhs are empty.
856  SDF_API
857  static std::string JoinIdentifier(const std::string &lhs,
858  const std::string &rhs);
859 
860  /// Join \p lhs and \p rhs into a single identifier using the
861  /// namespace delimiter.
862  /// Returns \p lhs if \p rhs is empty and vice verse.
863  /// Returns an empty string if both \p lhs and \p rhs are empty.
864  SDF_API
865  static std::string JoinIdentifier(const TfToken &lhs, const TfToken &rhs);
866 
867  /// Returns \p name stripped of any namespaces.
868  /// This does not check the validity of the name; it just attempts
869  /// to remove anything that looks like a namespace.
870  SDF_API
871  static std::string StripNamespace(const std::string &name);
872 
873  /// Returns \p name stripped of any namespaces.
874  /// This does not check the validity of the name; it just attempts
875  /// to remove anything that looks like a namespace.
876  SDF_API
877  static TfToken StripNamespace(const TfToken &name);
878 
879  /// Returns (\p name, \c true) where \p name is stripped of the prefix
880  /// specified by \p matchNamespace if \p name indeed starts with
881  /// \p matchNamespace. Returns (\p name, \c false) otherwise, with \p name
882  /// unmodified.
883  ///
884  /// This function deals with both the case where \p matchNamespace contains
885  /// the trailing namespace delimiter ':' or not.
886  ///
887  SDF_API
888  static std::pair<std::string, bool>
889  StripPrefixNamespace(const std::string &name,
890  const std::string &matchNamespace);
891 
892  /// Return true if \p pathString is a valid path string, meaning that
893  /// passing the string to the \a SdfPath constructor will result in a valid,
894  /// non-empty SdfPath. Otherwise, return false and if \p errMsg is not NULL,
895  /// set the pointed-to string to the parse error.
896  SDF_API
897  static bool IsValidPathString(const std::string &pathString,
898  std::string *errMsg = 0);
899 
900  /// @}
901 
902  /// \name Operators
903  /// @{
904 
905  /// Equality operator.
906  inline bool operator==(const SdfPath &rhs) const {
907  return _AsInt() == rhs._AsInt();
908  }
909 
910  /// Inequality operator.
911  inline bool operator!=(const SdfPath &rhs) const {
912  return !(*this == rhs);
913  }
914 
915  /// Comparison operator.
916  ///
917  /// This orders paths lexicographically, aka dictionary-style.
918  ///
919  inline bool operator<(const SdfPath &rhs) const {
920  if (_AsInt() == rhs._AsInt()) {
921  return false;
922  }
923  if (!_primPart || !rhs._primPart) {
924  return !_primPart && rhs._primPart;
925  }
926  // Valid prim parts -- must walk node structure, etc.
927  return _LessThanInternal(*this, rhs);
928  }
929 
930  /// Greater than operator.
931  /// \sa SdfPath::operator<(const SdfPath&)
932  inline bool operator>(const SdfPath& rhs) const {
933  return rhs < *this;
934  }
935 
936  /// Less than or equal operator.
937  /// \sa SdfPath::operator<(const SdfPath&)
938  inline bool operator<=(const SdfPath& rhs) const {
939  return !(rhs < *this);
940  }
941 
942  /// Greater than or equal operator.
943  /// \sa SdfPath::operator<(const SdfPath&)
944  inline bool operator>=(const SdfPath& rhs) const {
945  return !(*this < rhs);
946  }
947 
948  template <class HashState>
949  friend void TfHashAppend(HashState &h, SdfPath const &path) {
950  // The hash function is pretty sensitive performance-wise. Be
951  // careful making changes here, and run tests.
952  uint32_t primPart, propPart;
953  memcpy(&primPart, &path._primPart, sizeof(primPart));
954  memcpy(&propPart, &path._propPart, sizeof(propPart));
955  h.Append(primPart);
956  h.Append(propPart);
957  }
958 
959  // For hash maps and sets
960  struct Hash {
961  inline size_t operator()(const SdfPath& path) const {
962  return TfHash()(path);
963  }
964  };
965 
966  inline size_t GetHash() const {
967  return Hash()(*this);
968  }
969 
970  // For cases where an unspecified total order that is not stable from
971  // run-to-run is needed.
972  struct FastLessThan {
973  inline bool operator()(const SdfPath& a, const SdfPath& b) const {
974  return a._AsInt() < b._AsInt();
975  }
976  };
977 
978  /// @}
979 
980  /// \name Utilities
981  /// @{
982 
983  /// Given some vector of paths, get a vector of concise unambiguous
984  /// relative paths.
985  ///
986  /// GetConciseRelativePaths requires a vector of absolute paths. It
987  /// finds a set of relative paths such that each relative path is
988  /// unique.
989  SDF_API static SdfPathVector
990  GetConciseRelativePaths(const SdfPathVector& paths);
991 
992  /// Remove all elements of \a paths that are prefixed by other
993  /// elements in \a paths. As a side-effect, the result is left in sorted
994  /// order.
995  SDF_API static void RemoveDescendentPaths(SdfPathVector *paths);
996 
997  /// Remove all elements of \a paths that prefix other elements in
998  /// \a paths. As a side-effect, the result is left in sorted order.
999  SDF_API static void RemoveAncestorPaths(SdfPathVector *paths);
1000 
1001  /// @}
1002 
1003 private:
1004 
1005  // This is used for all internal path construction where we do operations
1006  // via nodes and then want to return a new path with a resulting prim and
1007  // property parts.
1008 
1009  // Accept rvalues.
1010  explicit SdfPath(Sdf_PathPrimNodeHandle &&primNode)
1011  : _primPart(std::move(primNode)) {}
1012 
1013  SdfPath(Sdf_PathPrimNodeHandle &&primPart,
1014  Sdf_PathPropNodeHandle &&propPart)
1015  : _primPart(std::move(primPart))
1016  , _propPart(std::move(propPart)) {}
1017 
1018  // Construct from prim & prop parts.
1019  SdfPath(Sdf_PathPrimNodeHandle const &primPart,
1020  Sdf_PathPropNodeHandle const &propPart)
1021  : _primPart(primPart)
1022  , _propPart(propPart) {}
1023 
1024  // Construct from prim & prop node pointers.
1025  SdfPath(Sdf_PathNode const *primPart,
1026  Sdf_PathNode const *propPart)
1027  : _primPart(primPart)
1028  , _propPart(propPart) {}
1029 
1030  friend class Sdf_PathNode;
1031  friend class Sdfext_PathAccess;
1033  friend class Sdf_PathInitAccess;
1034 
1035  SdfPath _ReplacePrimPrefix(SdfPath const &oldPrefix,
1036  SdfPath const &newPrefix) const;
1037 
1038  SdfPath _ReplaceTargetPathPrefixes(SdfPath const &oldPrefix,
1039  SdfPath const &newPrefix) const;
1040 
1041  SdfPath _ReplacePropPrefix(SdfPath const &oldPrefix,
1042  SdfPath const &newPrefix,
1043  bool fixTargetPaths) const;
1044 
1045  // Helper to implement the uninlined portion of operator<.
1046  SDF_API static bool
1047  _LessThanInternal(SdfPath const &lhs, SdfPath const &rhs);
1048 
1049  inline uint64_t _AsInt() const {
1050  static_assert(sizeof(*this) == sizeof(uint64_t), "");
1051  uint64_t ret;
1052  std::memcpy(&ret, this, sizeof(*this));
1053  return ret;
1054  }
1055 
1056  friend void swap(SdfPath &lhs, SdfPath &rhs) {
1057  lhs._primPart.swap(rhs._primPart);
1058  lhs._propPart.swap(rhs._propPart);
1059  }
1060 
1061  SDF_API friend char const *
1062  Sdf_PathGetDebuggerPathText(SdfPath const &);
1063 
1064  Sdf_PathPrimNodeHandle _primPart;
1065  Sdf_PathPropNodeHandle _propPart;
1066 
1067 };
1068 
1069 
1070 /// \class SdfPathAncestorsRange
1071 ///
1072 /// Range representing a path and ancestors, and providing methods for
1073 /// iterating over them.
1074 ///
1075 /// An ancestor range represents a path and all of its ancestors ordered from
1076 /// nearest to furthest (root-most).
1077 /// For example, given a path like `/a/b.prop`, the range represents paths
1078 /// `/a/b.prop`, `/a/b` and `/a`, in that order.
1079 /// A range accepts relative paths as well: For path `a/b.prop`, the range
1080 /// represents paths `a/b.prop`, `a/b` and `a`.
1081 /// If a path contains parent path elements, (`..`), those elements are treated
1082 /// as elements of the range. For instance, given path `../a/b`, the range
1083 /// represents paths `../a/b`, `../a` and `..`.
1084 /// This represents the same of set of `prefix` paths as SdfPath::GetPrefixes,
1085 /// but in reverse order.
1087 {
1088 public:
1089 
1090  SdfPathAncestorsRange(const SdfPath& path)
1091  : _path(path) {}
1092 
1093  const SdfPath& GetPath() const { return _path; }
1094 
1095  struct iterator {
1096  using iterator_category = std::forward_iterator_tag;
1097  using value_type = SdfPath;
1098  using difference_type = std::ptrdiff_t;
1099  using reference = const SdfPath&;
1100  using pointer = const SdfPath*;
1101 
1102  iterator(const SdfPath& path) : _path(path) {}
1103 
1104  iterator() = default;
1105 
1106  SDF_API
1107  iterator& operator++();
1108 
1109  const SdfPath& operator*() const { return _path; }
1110 
1111  const SdfPath* operator->() const { return &_path; }
1112 
1113  bool operator==(const iterator& o) const { return _path == o._path; }
1114 
1115  bool operator!=(const iterator& o) const { return _path != o._path; }
1116 
1117  /// Return the distance between two iterators.
1118  /// It is only valid to compute the distance between paths
1119  /// that share a common prefix.
1120  SDF_API friend difference_type
1121  distance(const iterator& first, const iterator& last);
1122 
1123  private:
1124  SdfPath _path;
1125  };
1126 
1127  iterator begin() const { return iterator(_path); }
1128 
1129  iterator end() const { return iterator(); }
1130 
1131 private:
1132  SdfPath _path;
1133 };
1134 
1135 
1136 // Overload hash_value for SdfPath. Used by things like boost::hash.
1137 inline size_t hash_value(SdfPath const &path)
1138 {
1139  return path.GetHash();
1140 }
1141 
1142 /// Writes the string representation of \p path to \p out.
1143 SDF_API std::ostream & operator<<( std::ostream &out, const SdfPath &path );
1144 
1145 // Helper for SdfPathFindPrefixedRange & SdfPathFindLongestPrefix. A function
1146 // object that returns an SdfPath const & unchanged.
1148  inline SdfPath const &operator()(SdfPath const &arg) const {
1149  return arg;
1150  }
1151 };
1152 
1153 /// Find the subrange of the sorted range [\a begin, \a end) that includes all
1154 /// paths prefixed by \a path. The input range must be ordered according to
1155 /// SdfPath::operator<. If your range's iterators' value_types are not SdfPath,
1156 /// but you can obtain SdfPaths from them (e.g. map<SdfPath, X>::iterator), you
1157 /// can pass a function to extract the path from the dereferenced iterator in
1158 /// \p getPath.
1159 template <class ForwardIterator, class GetPathFn = Sdf_PathIdentity>
1160 std::pair<ForwardIterator, ForwardIterator>
1161 SdfPathFindPrefixedRange(ForwardIterator begin, ForwardIterator end,
1162  SdfPath const &prefix,
1163  GetPathFn const &getPath = GetPathFn()) {
1164  using IterRef =
1166 
1167  struct Compare {
1168  Compare(GetPathFn const &getPath) : _getPath(getPath) {}
1169  GetPathFn const &_getPath;
1170  bool operator()(IterRef a, SdfPath const &b) const {
1171  return _getPath(a) < b;
1172  }
1173  };
1174 
1175  std::pair<ForwardIterator, ForwardIterator> result;
1176 
1177  // First, use lower_bound to find where \a prefix would go.
1178  result.first = std::lower_bound(begin, end, prefix, Compare(getPath));
1179 
1180  // Next, find end of range starting from the lower bound, using the
1181  // prefixing condition to define the boundary.
1182  result.second = TfFindBoundary(result.first, end,
1183  [&prefix, &getPath](IterRef iterRef) {
1184  return getPath(iterRef).HasPrefix(prefix);
1185  });
1186 
1187  return result;
1188 }
1189 
1190 template <class RandomAccessIterator, class GetPathFn>
1191 RandomAccessIterator
1193  RandomAccessIterator end,
1194  SdfPath const &path,
1195  bool strictPrefix,
1196  GetPathFn const &getPath)
1197 {
1198  using IterRef =
1200 
1201  struct Compare {
1202  Compare(GetPathFn const &getPath) : _getPath(getPath) {}
1203  GetPathFn const &_getPath;
1204  bool operator()(IterRef a, SdfPath const &b) const {
1205  return _getPath(a) < b;
1206  }
1207  };
1208 
1209  // Search for the path in [begin, end). If present, return it. If not,
1210  // examine prior element in [begin, end). If none, return end. Else, is it
1211  // a prefix of path? If so, return it. Else find common prefix of that
1212  // element and path and recurse.
1213 
1214  // If empty sequence, return.
1215  if (begin == end)
1216  return end;
1217 
1218  Compare comp(getPath);
1219 
1220  // Search for where this path would lexicographically appear in the range.
1221  RandomAccessIterator result = std::lower_bound(begin, end, path, comp);
1222 
1223  // If we didn't get the end, check to see if we got the path exactly if
1224  // we're not looking for a strict prefix.
1225  if (!strictPrefix && result != end && getPath(*result) == path) {
1226  return result;
1227  }
1228 
1229  // If we got begin (and didn't match in the case of a non-strict prefix)
1230  // then there's no prefix.
1231  if (result == begin) {
1232  return end;
1233  }
1234 
1235  // If the prior element is a prefix, we're done.
1236  if (path.HasPrefix(getPath(*--result))) {
1237  return result;
1238  }
1239 
1240  // Otherwise, find the common prefix of the lexicographical predecessor and
1241  // look for its prefix in the preceding range.
1242  SdfPath newPath = path.GetCommonPrefix(getPath(*result));
1243  auto origEnd = end;
1244  do {
1245  end = result;
1246  result = std::lower_bound(begin, end, newPath, comp);
1247 
1248  if (result != end && getPath(*result) == newPath) {
1249  return result;
1250  }
1251  if (result == begin) {
1252  return origEnd;
1253  }
1254  if (newPath.HasPrefix(getPath(*--result))) {
1255  return result;
1256  }
1257  newPath = newPath.GetCommonPrefix(getPath(*result));
1258  } while (true);
1259 }
1260 
1261 /// Return an iterator to the element of [\a begin, \a end) that is the longest
1262 /// prefix of the given path (including the path itself), if there is such an
1263 /// element, otherwise \a end. The input range must be ordered according to
1264 /// SdfPath::operator<. If your range's iterators' value_types are not SdfPath,
1265 /// but you can obtain SdfPaths from them (e.g. vector<pair<SdfPath,
1266 /// X>>::iterator), you can pass a function to extract the path from the
1267 /// dereferenced iterator in \p getPath.
1268 template <class RandomAccessIterator, class GetPathFn = Sdf_PathIdentity,
1269  class = typename std::enable_if<
1270  std::is_base_of<
1271  std::random_access_iterator_tag,
1272  typename std::iterator_traits<
1273  RandomAccessIterator>::iterator_category
1274  >::value
1275  >::type
1276  >
1277 RandomAccessIterator
1278 SdfPathFindLongestPrefix(RandomAccessIterator begin,
1279  RandomAccessIterator end,
1280  SdfPath const &path,
1281  GetPathFn const &getPath = GetPathFn())
1282 {
1284  begin, end, path, /*strictPrefix=*/false, getPath);
1285 }
1286 
1287 /// Return an iterator to the element of [\a begin, \a end) that is the longest
1288 /// prefix of the given path (excluding the path itself), if there is such an
1289 /// element, otherwise \a end. The input range must be ordered according to
1290 /// SdfPath::operator<. If your range's iterators' value_types are not SdfPath,
1291 /// but you can obtain SdfPaths from them (e.g. vector<pair<SdfPath,
1292 /// X>>::iterator), you can pass a function to extract the path from the
1293 /// dereferenced iterator in \p getPath.
1294 template <class RandomAccessIterator, class GetPathFn = Sdf_PathIdentity,
1295  class = typename std::enable_if<
1296  std::is_base_of<
1297  std::random_access_iterator_tag,
1298  typename std::iterator_traits<
1299  RandomAccessIterator>::iterator_category
1300  >::value
1301  >::type
1302  >
1303 RandomAccessIterator
1304 SdfPathFindLongestStrictPrefix(RandomAccessIterator begin,
1305  RandomAccessIterator end,
1306  SdfPath const &path,
1307  GetPathFn const &getPath = GetPathFn())
1308 {
1310  begin, end, path, /*strictPrefix=*/true, getPath);
1311 }
1312 
1313 template <class Iter, class MapParam, class GetPathFn = Sdf_PathIdentity>
1314 Iter
1316  MapParam map, SdfPath const &path, bool strictPrefix,
1317  GetPathFn const &getPath = GetPathFn())
1318 {
1319  // Search for the path in map. If present, return it. If not, examine
1320  // prior element in map. If none, return end. Else, is it a prefix of
1321  // path? If so, return it. Else find common prefix of that element and
1322  // path and recurse.
1323 
1324  const Iter mapEnd = map.end();
1325 
1326  // If empty, return.
1327  if (map.empty())
1328  return mapEnd;
1329 
1330  // Search for where this path would lexicographically appear in the range.
1331  Iter result = map.lower_bound(path);
1332 
1333  // If we didn't get the end, check to see if we got the path exactly if
1334  // we're not looking for a strict prefix.
1335  if (!strictPrefix && result != mapEnd && getPath(*result) == path)
1336  return result;
1337 
1338  // If we got begin (and didn't match in the case of a non-strict prefix)
1339  // then there's no prefix.
1340  if (result == map.begin())
1341  return mapEnd;
1342 
1343  // If the prior element is a prefix, we're done.
1344  if (path.HasPrefix(getPath(*--result)))
1345  return result;
1346 
1347  // Otherwise, find the common prefix of the lexicographical predecessor and
1348  // recurse looking for it or its longest prefix in the preceding range. We
1349  // always pass strictPrefix=false, since now we're operating on prefixes of
1350  // the original caller's path.
1351  return Sdf_PathFindLongestPrefixImpl<Iter, MapParam>(
1352  map, path.GetCommonPrefix(getPath(*result)), /*strictPrefix=*/false,
1353  getPath);
1354 }
1355 
1356 /// Return an iterator pointing to the element of \a set whose key is the
1357 /// longest prefix of the given path (including the path itself). If there is
1358 /// no such element, return \a set.end().
1359 SDF_API
1360 typename std::set<SdfPath>::const_iterator
1361 SdfPathFindLongestPrefix(std::set<SdfPath> const &set, SdfPath const &path);
1362 
1363 /// Return an iterator pointing to the element of \a map whose key is the
1364 /// longest prefix of the given path (including the path itself). If there is
1365 /// no such element, return \a map.end().
1366 template <class T>
1367 typename std::map<SdfPath, T>::const_iterator
1368 SdfPathFindLongestPrefix(std::map<SdfPath, T> const &map, SdfPath const &path)
1369 {
1371  typename std::map<SdfPath, T>::const_iterator,
1372  std::map<SdfPath, T> const &>(map, path, /*strictPrefix=*/false,
1373  TfGet<0>());
1374 }
1375 template <class T>
1376 typename std::map<SdfPath, T>::iterator
1377 SdfPathFindLongestPrefix(std::map<SdfPath, T> &map, SdfPath const &path)
1378 {
1380  typename std::map<SdfPath, T>::iterator,
1381  std::map<SdfPath, T> &>(map, path, /*strictPrefix=*/false,
1382  TfGet<0>());
1383 }
1384 
1385 /// Return an iterator pointing to the element of \a set whose key is the
1386 /// longest prefix of the given path (excluding the path itself). If there is
1387 /// no such element, return \a set.end().
1388 SDF_API
1389 typename std::set<SdfPath>::const_iterator
1390 SdfPathFindLongestStrictPrefix(std::set<SdfPath> const &set,
1391  SdfPath const &path);
1392 
1393 /// Return an iterator pointing to the element of \a map whose key is the
1394 /// longest prefix of the given path (excluding the path itself). If there is
1395 /// no such element, return \a map.end().
1396 template <class T>
1397 typename std::map<SdfPath, T>::const_iterator
1399  std::map<SdfPath, T> const &map, SdfPath const &path)
1400 {
1402  typename std::map<SdfPath, T>::const_iterator,
1403  std::map<SdfPath, T> const &>(map, path, /*strictPrefix=*/true,
1404  TfGet<0>());
1405 }
1406 template <class T>
1407 typename std::map<SdfPath, T>::iterator
1409  std::map<SdfPath, T> &map, SdfPath const &path)
1410 {
1412  typename std::map<SdfPath, T>::iterator,
1413  std::map<SdfPath, T> &>(map, path, /*strictPrefix=*/true,
1414  TfGet<0>());
1415 }
1416 
1417 // A helper function for debugger pretty-printers, etc. This function is *not*
1418 // thread-safe. It writes to a static buffer and returns a pointer to it.
1419 // Subsequent calls to this function overwrite the memory written in prior
1420 // calls. If the given path's string representation exceeds the static buffer
1421 // size, return a pointer to a message indicating so.
1422 SDF_API
1423 char const *
1424 Sdf_PathGetDebuggerPathText(SdfPath const &);
1425 
1427 
1428 // Sdf_PathNode is not public API, but we need to include it here
1429 // so we can inline the ref-counting operations, which must manipulate
1430 // its internal _refCount member.
1431 #include "pxr/usd/sdf/pathNode.h"
1432 
1433 #endif // PXR_USD_SDF_PATH_H
SDF_API const char * GetText() const
GLint first
Definition: glcorearb.h:405
SDF_API bool IsPrimOrPrimVariantSelectionPath() const
SDF_API SdfPath AppendTarget(const SdfPath &targetPath) const
SDF_API bool IsMapperPath() const
Returns whether the path identifies a connection mapper.
friend void swap(SdfPath &lhs, SdfPath &rhs)
Definition: path.h:1056
SDF_API iterator & operator++()
SDF_API const std::string & GetName() const
static SDF_API const SdfPath & AbsoluteRootPath()
friend class Sdfext_PathAccess
Definition: path.h:1031
static constexpr bool IsCounted
Definition: path.h:75
Sdf_PathNodeHandleImpl(Sdf_PathNodeHandleImpl const &rhs) noexcept
Definition: path.h:95
SDF_API std::string GetElementString() const
SDF_API bool IsExpressionPath() const
Returns whether the path identifies a connection expression.
SDF_API SdfPath AppendExpression() const
iterator(const SdfPath &path)
Definition: path.h:1102
Sdf_PathNodeHandleImpl(Handle h, bool add_ref=true)
Definition: path.h:88
SDF_API SdfPath AppendMapper(const SdfPath &targetPath) const
STATIC_INLINE size_t Hash(const char *s, size_t len)
Definition: farmhash.h:2099
friend class Sdf_PathInitAccess
Definition: path.h:1033
SDF_API char const * Sdf_PathGetDebuggerPathText(SdfPath const &)
bool operator==(const SdfPath &rhs) const
Equality operator.
Definition: path.h:906
Sdf_PathPropPartPool::Handle Sdf_PathPropHandle
Definition: path.h:66
SDF_API SdfPath ReplaceTargetPath(const SdfPath &newTargetPath) const
void reset() noexcept
Definition: path.h:134
std::pair< ForwardIterator, ForwardIterator > SdfPathFindPrefixedRange(ForwardIterator begin, ForwardIterator end, SdfPath const &prefix, GetPathFn const &getPath=GetPathFn())
Definition: path.h:1161
static SDF_API bool IsValidPathString(const std::string &pathString, std::string *errMsg=0)
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
GLsizei const GLfloat * value
Definition: glcorearb.h:824
RandomAccessIterator Sdf_PathFindLongestPrefixImpl(RandomAccessIterator begin, RandomAccessIterator end, SdfPath const &path, bool strictPrefix, GetPathFn const &getPath)
Definition: path.h:1192
SDF_API bool IsAbsoluteRootPath() const
Return true if this path is the AbsoluteRootPath().
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
SDF_API bool IsMapperArgPath() const
Returns whether the path identifies a connection mapper arg.
void TfDelegatedCountIncrement(Sdf_PathNode const *) noexcept
SDF_API const SdfPath & GetTargetPath() const
SDF_API bool IsPrimPropertyPath() const
SDF_API SdfPath GetAbsoluteRootOrPrimPath() const
SdfPathAncestorsRange(const SdfPath &path)
Definition: path.h:1090
SDF_API TfToken GetAsToken() const
Sdf_PathNodeHandleImpl & operator=(Sdf_PathNodeHandleImpl &&rhs) noexcept
Definition: path.h:123
bool operator==(const iterator &o) const
Definition: path.h:1113
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
static SDF_API void RemoveDescendentPaths(SdfPathVector *paths)
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
Definition: path.h:405
bool operator==(Sdf_PathNodeHandleImpl const &rhs) const noexcept
Definition: path.h:161
**But if you need a result
Definition: thread.h:622
Sdf_PathNodeHandleImpl(Sdf_PathNode const *p, bool add_ref=true)
Definition: path.h:80
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Definition: core.h:1859
SdfPath const & operator()(SdfPath const &arg) const
Definition: path.h:1148
size_t GetHash() const
Equality operator.
Definition: path.h:966
OutGridT const XformOp bool bool
SDF_API std::pair< std::string, std::string > GetVariantSelection() const
SDF_API SdfPath StripAllVariantSelections() const
bool operator!=(const iterator &o) const
Definition: path.h:1115
SDF_API SdfPath AppendRelationalAttribute(TfToken const &attrName) const
Definition: hash.h:472
static SDF_API std::vector< std::string > TokenizeIdentifier(const std::string &name)
static SDF_API const SdfPath & EmptyPath()
The empty path value, equivalent to SdfPath().
const SdfPath & operator*() const
Definition: path.h:1109
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
Definition: token.h:70
bool operator<(const SdfPath &rhs) const
Definition: path.h:919
void swap(Sdf_PathNodeHandleImpl &rhs) noexcept
Definition: path.h:157
friend void TfHashAppend(HashState &h, SdfPath const &path)
Equality operator.
Definition: path.h:949
SDF_API void GetAllTargetPathsRecursively(SdfPathVector *result) const
bool ContainsPropertyElements() const
Definition: path.h:378
SDF_API bool IsPrimVariantSelectionPath() const
bool operator!=(Sdf_PathNodeHandleImpl const &rhs) const noexcept
Definition: path.h:164
SDF_API SdfPath AppendChild(TfToken const &childName) const
constexpr auto set(type rhs) -> int
Definition: core.h:610
Definition: span.h:70
static SDF_API bool IsValidNamespacedIdentifier(const std::string &name)
Sdf_PathNode const & operator*() const
Definition: path.h:144
bool operator>=(const SdfPath &rhs) const
Definition: path.h:944
GLuint GLuint end
Definition: glcorearb.h:475
SDF_API SdfPath AppendVariantSelection(const std::string &variantSet, const std::string &variant) const
SDF_API SdfPath AppendMapperArg(TfToken const &argName) const
SDF_API bool IsAbsolutePath() const
Returns whether the path is absolute.
static SDF_API std::string JoinIdentifier(const std::vector< std::string > &names)
std::vector< TfToken > TfTokenVector
Convenience types.
Definition: token.h:440
SDF_API bool ContainsTargetPath() const
static SDF_API bool IsValidIdentifier(const std::string &name)
SdfPath() noexcept=default
SDF_API size_t GetPathElementCount() const
Returns the number of path elements in this path.
GLuint const GLchar * name
Definition: glcorearb.h:786
Definition: stl.h:361
Definition: path.h:280
SDF_API TfToken GetElementToken() const
Like GetElementString() but return the value as a TfToken.
SDF_API const std::string & GetString() const
SDF_API bool IsPrimPath() const
Returns whether the path identifies a prim.
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
size_t operator()(const SdfPath &path) const
Definition: path.h:961
Sdf_PathPrimPartPool::Handle Sdf_PathPrimHandle
Definition: path.h:65
Sdf_PathNodeHandleImpl & operator=(Sdf_PathNode const *rhs) noexcept
Definition: path.h:129
std::vector< class SdfPath > SdfPathVector
A vector of SdfPaths.
Definition: path.h:201
constexpr Sdf_PathNodeHandleImpl() noexcept
Definition: path.h:77
SDF_API const TfToken & GetNameToken() const
SDF_API bool HasPrefix(const SdfPath &prefix) const
SDF_API bool IsRelationalAttributePath() const
std::set< class SdfPath > SdfPathSet
A set of SdfPaths.
Definition: path.h:199
SDF_API SdfPath AppendProperty(TfToken const &propName) const
SDF_API bool ContainsPrimVariantSelection() const
__hostdev__ uint64_t last(uint32_t i) const
Definition: NanoVDB.h:5976
std::forward_iterator_tag iterator_category
Definition: path.h:1096
#define SDF_API
Definition: api.h:23
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
bool operator<(Sdf_PathNodeHandleImpl const &rhs) const noexcept
Definition: path.h:167
SDF_API std::ostream & operator<<(std::ostream &out, const SdfPath &path)
Writes the string representation of path to out.
const SdfPath * operator->() const
Definition: path.h:1111
SDF_API SdfPathAncestorsRange GetAncestorsRange() const
SDF_API SdfPath GetCommonPrefix(const SdfPath &path) const
SDF_API TfToken const & GetToken() const
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:587
SDF_API bool IsTargetPath() const
iterator end() const
Definition: path.h:1129
Sdf_PathNodeHandleImpl & operator=(Sdf_PathNodeHandleImpl const &rhs)
Definition: path.h:109
SDF_API std::pair< SdfPath, SdfPath > RemoveCommonSuffix(const SdfPath &otherPath, bool stopAtRootPrim=false) const
size_t hash_value(SdfPath const &path)
Definition: path.h:1137
SDF_API bool IsRootPrimPath() const
SDF_API SdfPath AppendPath(const SdfPath &newSuffix) const
SDF_API std::string GetAsString() const
const SdfPath & GetPath() const
Definition: path.h:1093
iterator begin() const
Definition: path.h:1127
SDF_API SdfPath MakeAbsolutePath(const SdfPath &anchor) const
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
SDF_API bool IsNamespacedPropertyPath() const
SDF_API SdfPath AppendElementToken(const TfToken &elementTok) const
Like AppendElementString() but take the element as a TfToken.
SDF_API SdfPath GetParentPath() const
static SDF_API SdfPathVector GetConciseRelativePaths(const SdfPathVector &paths)
SDF_API SdfPath GetPrimOrPrimVariantSelectionPath() const
SDF_API bool IsPropertyPath() const
static SDF_API std::pair< std::string, bool > StripPrefixNamespace(const std::string &name, const std::string &matchNamespace)
SDF_API friend char const * Sdf_PathGetDebuggerPathText(SdfPath const &)
SDF_API friend difference_type distance(const iterator &first, const iterator &last)
RandomAccessIterator SdfPathFindLongestPrefix(RandomAccessIterator begin, RandomAccessIterator end, SdfPath const &path, GetPathFn const &getPath=GetPathFn())
Definition: path.h:1278
static SDF_API void RemoveAncestorPaths(SdfPathVector *paths)
SDF_API bool IsAbsoluteRootOrPrimPath() const
Returns whether the path identifies a prim or the absolute root.
RandomAccessIterator SdfPathFindLongestStrictPrefix(RandomAccessIterator begin, RandomAccessIterator end, SdfPath const &path, GetPathFn const &getPath=GetPathFn())
Definition: path.h:1304
Sdf_PathNode const * operator->() const
Definition: path.h:149
bool operator!=(const SdfPath &rhs) const
Inequality operator.
Definition: path.h:911
Sdf_PathNodeHandleImpl(Sdf_PathNodeHandleImpl &&rhs) noexcept
Definition: path.h:117
SDF_API SdfPathVector GetPrefixes() const
static SDF_API std::string StripNamespace(const std::string &name)
that also have some descendant prim *whose name begins with which in turn has a child named baz where *the predicate and *a name There is also one special expression reference
friend struct Handle
Definition: pool.h:77
SDF_API SdfPath ReplaceName(TfToken const &newName) const
bool operator<=(const SdfPath &rhs) const
Definition: path.h:938
static SDF_API const SdfPath & ReflexiveRelativePath()
The relative path representing "self".
bool operator>(const SdfPath &rhs) const
Definition: path.h:932
SDF_API SdfPath AppendElementString(const std::string &element) const
bool operator()(const SdfPath &a, const SdfPath &b) const
Definition: path.h:973
VT_TYPE_IS_CHEAP_TO_COPY(class SdfPath)
Definition: pool.h:62
std::ptrdiff_t difference_type
Definition: path.h:1098
void TfDelegatedCountDecrement(Sdf_PathNode const *) noexcept
SDF_API SdfPath MakeRelativePath(const SdfPath &anchor) const
SDF_API SdfPath ReplacePrefix(const SdfPath &oldPrefix, const SdfPath &newPrefix, bool fixTargetPaths=true) const
SDF_API SdfPath GetPrimPath() const
void * Handle
Definition: plugin.h:27
static SDF_API TfTokenVector TokenizeIdentifierAsTokens(const std::string &name)