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