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