Loading...
Searching...
No Matches
path.h
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"
15#include "pxr/base/tf/delegatedCountPtr.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
29PXR_NAMESPACE_OPEN_SCOPE
30
31class 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
41void TfDelegatedCountIncrement(Sdf_PathNode const *) noexcept;
42void TfDelegatedCountDecrement(Sdf_PathNode const *) noexcept;
43
44// Tags used for the pools of path nodes.
45struct Sdf_PathPrimTag;
46struct Sdf_PathPropTag;
47
48
49// The sizes below represent the largest sizes of the prim and property
50// Sdf_PathNode subclasses.
51#ifdef ARCH_BITS_32
52static constexpr size_t Sdf_MaxSizeofPrimPathNode = 16;
53static constexpr size_t Sdf_MaxSizeofPropPathNode = 20;
54#else
55static constexpr size_t Sdf_MaxSizeofPrimPathNode = 24;
56static constexpr size_t Sdf_MaxSizeofPropPathNode = 24;
57#endif
58
59using Sdf_PathPrimPartPool = Sdf_Pool<
60 Sdf_PathPrimTag, Sdf_MaxSizeofPrimPathNode, /*regionBits=*/8>;
61
62using Sdf_PathPropPartPool = Sdf_Pool<
63 Sdf_PathPropTag, Sdf_MaxSizeofPropPathNode, /*regionBits=*/8>;
64
65using Sdf_PathPrimHandle = Sdf_PathPrimPartPool::Handle;
66using Sdf_PathPropHandle = Sdf_PathPropPartPool::Handle;
67
68// This handle class wraps up the raw Prim/PropPartPool handles.
69template <class Handle, bool Counted, class PathNode=Sdf_PathNode const>
70struct Sdf_PathNodeHandleImpl {
71private:
72 typedef Sdf_PathNodeHandleImpl this_type;
73
74public:
75 static constexpr bool IsCounted = Counted;
76
77 constexpr Sdf_PathNodeHandleImpl() noexcept {};
78
79 explicit
80 Sdf_PathNodeHandleImpl(Sdf_PathNode const *p, bool add_ref = true)
81 : _poolHandle(Handle::GetHandle(reinterpret_cast<char const *>(p))) {
82 if (p && add_ref) {
83 _AddRef(p);
84 }
85 }
86
87 explicit
88 Sdf_PathNodeHandleImpl(Handle h, bool add_ref = true)
89 : _poolHandle(h) {
90 if (h && add_ref) {
91 _AddRef();
92 }
93 }
94
95 Sdf_PathNodeHandleImpl(Sdf_PathNodeHandleImpl const &rhs) noexcept
96 : _poolHandle(rhs._poolHandle) {
97 if (_poolHandle) {
98 _AddRef();
99 }
100 }
101
102 ~Sdf_PathNodeHandleImpl() {
103 if (_poolHandle) {
104 _DecRef();
105 }
106 }
107
108 Sdf_PathNodeHandleImpl &
109 operator=(Sdf_PathNodeHandleImpl const &rhs) {
110 if (Counted && *this == rhs) {
111 return *this;
112 }
113 this_type(rhs).swap(*this);
114 return *this;
115 }
116
117 Sdf_PathNodeHandleImpl(Sdf_PathNodeHandleImpl &&rhs) noexcept
118 : _poolHandle(rhs._poolHandle) {
119 rhs._poolHandle = nullptr;
120 }
121
122 Sdf_PathNodeHandleImpl &
123 operator=(Sdf_PathNodeHandleImpl &&rhs) noexcept {
124 this_type(std::move(rhs)).swap(*this);
125 return *this;
126 }
127
128 Sdf_PathNodeHandleImpl &
129 operator=(Sdf_PathNode const *rhs) noexcept {
130 this_type(rhs).swap(*this);
131 return *this;
132 }
133
134 void reset() noexcept {
135 _poolHandle = Handle { nullptr };
136 }
137
138 inline Sdf_PathNode const *
139 get() const noexcept {
140 return reinterpret_cast<Sdf_PathNode *>(_poolHandle.GetPtr());
141 }
142
143 Sdf_PathNode const &
144 operator*() const {
145 return *get();
146 }
147
148 Sdf_PathNode const *
149 operator->() const {
150 return get();
151 }
152
153 explicit operator bool() const noexcept {
154 return static_cast<bool>(_poolHandle);
155 }
156
157 void swap(Sdf_PathNodeHandleImpl &rhs) noexcept {
158 _poolHandle.swap(rhs._poolHandle);
159 }
160
161 inline bool operator==(Sdf_PathNodeHandleImpl const &rhs) const noexcept {
162 return _poolHandle == rhs._poolHandle;
163 }
164 inline bool operator!=(Sdf_PathNodeHandleImpl const &rhs) const noexcept {
165 return _poolHandle != rhs._poolHandle;
166 }
167 inline bool operator<(Sdf_PathNodeHandleImpl const &rhs) const noexcept {
168 return _poolHandle < rhs._poolHandle;
169 }
170private:
171
172 inline void _AddRef(Sdf_PathNode const *p) const {
173 if (Counted) {
174 TfDelegatedCountIncrement(p);
175 }
176 }
177
178 inline void _AddRef() const {
179 _AddRef(get());
180 }
181
182 inline void _DecRef() const {
183 if (Counted) {
184 TfDelegatedCountDecrement(get());
185 }
186 }
187
188 Handle _poolHandle { nullptr };
189};
190
191using Sdf_PathPrimNodeHandle =
192 Sdf_PathNodeHandleImpl<Sdf_PathPrimHandle, /*Counted=*/true>;
193
194using Sdf_PathPropNodeHandle =
195 Sdf_PathNodeHandleImpl<Sdf_PathPropHandle, /*Counted=*/false>;
196
197
199typedef std::set<class SdfPath> SdfPathSet;
201typedef std::vector<class SdfPath> SdfPathVector;
202
203// Tell VtValue that SdfPath is cheap to copy.
204VT_TYPE_IS_CHEAP_TO_COPY(class SdfPath);
205
281{
282public:
284 SDF_API static const SdfPath & EmptyPath();
285
288 SDF_API static const SdfPath & AbsoluteRootPath();
289
291 SDF_API static const SdfPath & ReflexiveRelativePath();
292
295
298 SdfPath() noexcept = default;
299
312 //
313 // XXX We may want to revisit the behavior when constructing
314 // a path with an empty string ("") to accept it without error and
315 // return EmptyPath.
316 SDF_API explicit SdfPath(const std::string &path);
317
319
322
324 SDF_API size_t GetPathElementCount() const;
325
327 SDF_API bool IsAbsolutePath() const;
328
330 SDF_API bool IsAbsoluteRootPath() const;
331
333 SDF_API bool IsPrimPath() const;
334
336 SDF_API bool IsAbsoluteRootOrPrimPath() const;
337
342 SDF_API bool IsRootPrimPath() const;
343
349 SDF_API bool IsPropertyPath() const;
350
354 SDF_API bool IsPrimPropertyPath() const;
355
359 SDF_API bool IsNamespacedPropertyPath() const;
360
363 SDF_API bool IsPrimVariantSelectionPath() const;
364
368
371 SDF_API bool ContainsPrimVariantSelection() const;
372
379 return static_cast<bool>(_propPart);
380 }
381
384 SDF_API bool ContainsTargetPath() const;
385
389 SDF_API bool IsRelationalAttributePath() const;
390
393 SDF_API bool IsTargetPath() const;
394
396 SDF_API bool IsMapperPath() const;
397
399 SDF_API bool IsMapperArgPath() const;
400
402 SDF_API bool IsExpressionPath() const;
403
405 inline bool IsEmpty() const noexcept {
406 // No need to check _propPart, because it can only be non-null if
407 // _primPart is non-null.
408 return !_primPart;
409 }
410
416 SDF_API TfToken GetAsToken() const;
417
427 SDF_API TfToken const &GetToken() const;
428
434 SDF_API std::string GetAsString() const;
435
445 SDF_API const std::string &GetString() const;
446
457 SDF_API const char *GetText() const;
458
466 SDF_API SdfPathVector GetPrefixes() const;
467
476 SDF_API SdfPathVector GetPrefixes(size_t numPrefixes) const;
477
487 SDF_API void GetPrefixes(SdfPathVector *prefixes) const;
488
497 SDF_API void GetPrefixes(SdfPathVector *prefixes, size_t numPrefixes) const;
498
512
521
532 SDF_API const std::string &GetName() const;
533
536 SDF_API const TfToken &GetNameToken() const;
537
555 SDF_API std::string GetElementString() const;
556
558 SDF_API TfToken GetElementToken() const;
559
579 SDF_API SdfPath ReplaceName(TfToken const &newName) const;
580
593 SDF_API const SdfPath &GetTargetPath() const;
594
602 SDF_API void GetAllTargetPathsRecursively(SdfPathVector *result) const;
603
608 SDF_API
609 std::pair<std::string, std::string> GetVariantSelection() const;
610
613 SDF_API bool HasPrefix( const SdfPath &prefix ) const;
614
616
619
642 SDF_API SdfPath GetParentPath() const;
643
651 SDF_API SdfPath GetPrimPath() const;
652
662
669
674
682 SDF_API SdfPath AppendPath(const SdfPath &newSuffix) const;
683
689 SDF_API SdfPath AppendChild(TfToken const &childName) const;
690
695 SDF_API SdfPath AppendProperty(TfToken const &propName) const;
696
701 SDF_API
702 SdfPath AppendVariantSelection(const std::string &variantSet,
703 const std::string &variant) const;
704
709 SDF_API SdfPath AppendTarget(const SdfPath &targetPath) const;
710
715 SDF_API
717
721 SDF_API
722 SdfPath ReplaceTargetPath( const SdfPath &newTargetPath ) const;
723
728 SDF_API SdfPath AppendMapper(const SdfPath &targetPath) const;
729
734 SDF_API SdfPath AppendMapperArg(TfToken const &argName) const;
735
739 SDF_API SdfPath AppendExpression() const;
740
750 SDF_API SdfPath AppendElementString(const std::string &element) const;
751
753 SDF_API SdfPath AppendElementToken(const TfToken &elementTok) const;
754
764 SDF_API
765 SdfPath ReplacePrefix(const SdfPath &oldPrefix,
766 const SdfPath &newPrefix,
767 bool fixTargetPaths=true) const;
768
771 SDF_API SdfPath GetCommonPrefix(const SdfPath &path) const;
772
788 SDF_API
789 std::pair<SdfPath, SdfPath>
790 RemoveCommonSuffix(const SdfPath& otherPath,
791 bool stopAtRootPrim = false) const;
792
802 SDF_API SdfPath MakeAbsolutePath(const SdfPath & anchor) const;
803
816 SDF_API SdfPath MakeRelativePath(const SdfPath & anchor) const;
817
819
822
825 SDF_API static bool IsValidIdentifier(const std::string &name);
826
829 SDF_API static bool IsValidNamespacedIdentifier(const std::string &name);
830
834 SDF_API static std::vector<std::string> TokenizeIdentifier(const std::string &name);
835
839 SDF_API
840 static TfTokenVector TokenizeIdentifierAsTokens(const std::string &name);
841
844 SDF_API
845 static std::string JoinIdentifier(const std::vector<std::string> &names);
846
849 SDF_API
850 static std::string JoinIdentifier(const TfTokenVector& names);
851
856 SDF_API
857 static std::string JoinIdentifier(const std::string &lhs,
858 const std::string &rhs);
859
864 SDF_API
865 static std::string JoinIdentifier(const TfToken &lhs, const TfToken &rhs);
866
870 SDF_API
871 static std::string StripNamespace(const std::string &name);
872
876 SDF_API
877 static TfToken StripNamespace(const TfToken &name);
878
887 SDF_API
888 static std::pair<std::string, bool>
889 StripPrefixNamespace(const std::string &name,
890 const std::string &matchNamespace);
891
896 SDF_API
897 static bool IsValidPathString(const std::string &pathString,
898 std::string *errMsg = 0);
899
901
904
906 inline bool operator==(const SdfPath &rhs) const {
907 return _AsInt() == rhs._AsInt();
908 }
909
911 inline bool operator!=(const SdfPath &rhs) const {
912 return !(*this == rhs);
913 }
914
919 inline bool operator<(const SdfPath &rhs) const {
920 if (_AsInt() == rhs._AsInt()) {
921 return false;
922 }
923 if (!_primPart || !rhs._primPart) {
924 return !_primPart && rhs._primPart;
925 }
926 // Valid prim parts -- must walk node structure, etc.
927 return _LessThanInternal(*this, rhs);
928 }
929
932 inline bool operator>(const SdfPath& rhs) const {
933 return rhs < *this;
934 }
935
938 inline bool operator<=(const SdfPath& rhs) const {
939 return !(rhs < *this);
940 }
941
944 inline bool operator>=(const SdfPath& rhs) const {
945 return !(*this < rhs);
946 }
947
948 template <class HashState>
949 friend void TfHashAppend(HashState &h, SdfPath const &path) {
950 // The hash function is pretty sensitive performance-wise. Be
951 // careful making changes here, and run tests.
952 uint32_t primPart, propPart;
953 memcpy(&primPart, &path._primPart, sizeof(primPart));
954 memcpy(&propPart, &path._propPart, sizeof(propPart));
955 h.Append(primPart);
956 h.Append(propPart);
957 }
958
959 // For hash maps and sets
960 struct Hash {
961 inline size_t operator()(const SdfPath& path) const {
962 return TfHash()(path);
963 }
964 };
965
966 inline size_t GetHash() const {
967 return Hash()(*this);
968 }
969
970 // For cases where an unspecified total order that is not stable from
971 // run-to-run is needed.
972 struct FastLessThan {
973 inline bool operator()(const SdfPath& a, const SdfPath& b) const {
974 return a._AsInt() < b._AsInt();
975 }
976 };
977
979
982
989 SDF_API static SdfPathVector
990 GetConciseRelativePaths(const SdfPathVector& paths);
991
995 SDF_API static void RemoveDescendentPaths(SdfPathVector *paths);
996
999 SDF_API static void RemoveAncestorPaths(SdfPathVector *paths);
1000
1002
1003private:
1004
1005 // This is used for all internal path construction where we do operations
1006 // via nodes and then want to return a new path with a resulting prim and
1007 // property parts.
1008
1009 // Accept rvalues.
1010 explicit SdfPath(Sdf_PathPrimNodeHandle &&primNode)
1011 : _primPart(std::move(primNode)) {}
1012
1013 SdfPath(Sdf_PathPrimNodeHandle &&primPart,
1014 Sdf_PathPropNodeHandle &&propPart)
1015 : _primPart(std::move(primPart))
1016 , _propPart(std::move(propPart)) {}
1017
1018 // Construct from prim & prop parts.
1019 SdfPath(Sdf_PathPrimNodeHandle const &primPart,
1020 Sdf_PathPropNodeHandle const &propPart)
1021 : _primPart(primPart)
1022 , _propPart(propPart) {}
1023
1024 // Construct from prim & prop node pointers.
1025 SdfPath(Sdf_PathNode const *primPart,
1026 Sdf_PathNode const *propPart)
1027 : _primPart(primPart)
1028 , _propPart(propPart) {}
1029
1030 friend class Sdf_PathNode;
1031 friend class Sdfext_PathAccess;
1032 friend class SdfPathAncestorsRange;
1033 friend class Sdf_PathInitAccess;
1034
1035 SdfPath _ReplacePrimPrefix(SdfPath const &oldPrefix,
1036 SdfPath const &newPrefix) const;
1037
1038 SdfPath _ReplaceTargetPathPrefixes(SdfPath const &oldPrefix,
1039 SdfPath const &newPrefix) const;
1040
1041 SdfPath _ReplacePropPrefix(SdfPath const &oldPrefix,
1042 SdfPath const &newPrefix,
1043 bool fixTargetPaths) const;
1044
1045 // Helper to implement the uninlined portion of operator<.
1046 SDF_API static bool
1047 _LessThanInternal(SdfPath const &lhs, SdfPath const &rhs);
1048
1049 inline uint64_t _AsInt() const {
1050 static_assert(sizeof(*this) == sizeof(uint64_t), "");
1051 uint64_t ret;
1052 std::memcpy(&ret, this, sizeof(*this));
1053 return ret;
1054 }
1055
1056 friend void swap(SdfPath &lhs, SdfPath &rhs) {
1057 lhs._primPart.swap(rhs._primPart);
1058 lhs._propPart.swap(rhs._propPart);
1059 }
1060
1061 SDF_API friend char const *
1062 Sdf_PathGetDebuggerPathText(SdfPath const &);
1063
1064 Sdf_PathPrimNodeHandle _primPart;
1065 Sdf_PathPropNodeHandle _propPart;
1066
1067};
1068
1069
1087{
1088public:
1089
1090 SdfPathAncestorsRange(const SdfPath& path)
1091 : _path(path) {}
1092
1093 const SdfPath& GetPath() const { return _path; }
1094
1095 struct iterator {
1096 using iterator_category = std::forward_iterator_tag;
1097 using value_type = SdfPath;
1098 using difference_type = std::ptrdiff_t;
1099 using reference = const SdfPath&;
1100 using pointer = const SdfPath*;
1101
1102 iterator(const SdfPath& path) : _path(path) {}
1103
1104 iterator() = default;
1105
1106 SDF_API
1107 iterator& operator++();
1108
1109 const SdfPath& operator*() const { return _path; }
1110
1111 const SdfPath* operator->() const { return &_path; }
1112
1113 bool operator==(const iterator& o) const { return _path == o._path; }
1114
1115 bool operator!=(const iterator& o) const { return _path != o._path; }
1116
1120 SDF_API friend difference_type
1121 distance(const iterator& first, const iterator& last);
1122
1123 private:
1124 SdfPath _path;
1125 };
1126
1127 iterator begin() const { return iterator(_path); }
1128
1129 iterator end() const { return iterator(); }
1130
1131private:
1132 SdfPath _path;
1133};
1134
1135
1136// Overload hash_value for SdfPath. Used by things like boost::hash.
1137inline size_t hash_value(SdfPath const &path)
1138{
1139 return path.GetHash();
1140}
1141
1143SDF_API std::ostream & operator<<( std::ostream &out, const SdfPath &path );
1144
1145// Helper for SdfPathFindPrefixedRange & SdfPathFindLongestPrefix. A function
1146// object that returns an SdfPath const & unchanged.
1147struct Sdf_PathIdentity {
1148 inline SdfPath const &operator()(SdfPath const &arg) const {
1149 return arg;
1150 }
1151};
1152
1159template <class ForwardIterator, class GetPathFn = Sdf_PathIdentity>
1160std::pair<ForwardIterator, ForwardIterator>
1161SdfPathFindPrefixedRange(ForwardIterator begin, ForwardIterator end,
1162 SdfPath const &prefix,
1163 GetPathFn const &getPath = GetPathFn()) {
1164 using IterRef =
1165 typename std::iterator_traits<ForwardIterator>::reference;
1166
1167 struct Compare {
1168 Compare(GetPathFn const &getPath) : _getPath(getPath) {}
1169 GetPathFn const &_getPath;
1170 bool operator()(IterRef a, SdfPath const &b) const {
1171 return _getPath(a) < b;
1172 }
1173 };
1174
1175 std::pair<ForwardIterator, ForwardIterator> result;
1176
1177 // First, use lower_bound to find where \a prefix would go.
1178 result.first = std::lower_bound(begin, end, prefix, Compare(getPath));
1179
1180 // Next, find end of range starting from the lower bound, using the
1181 // prefixing condition to define the boundary.
1182 result.second = TfFindBoundary(result.first, end,
1183 [&prefix, &getPath](IterRef iterRef) {
1184 return getPath(iterRef).HasPrefix(prefix);
1185 });
1186
1187 return result;
1188}
1189
1190template <class RandomAccessIterator, class GetPathFn>
1191RandomAccessIterator
1192Sdf_PathFindLongestPrefixImpl(RandomAccessIterator begin,
1193 RandomAccessIterator end,
1194 SdfPath const &path,
1195 bool strictPrefix,
1196 GetPathFn const &getPath)
1197{
1198 using IterRef =
1199 typename std::iterator_traits<RandomAccessIterator>::reference;
1200
1201 struct Compare {
1202 Compare(GetPathFn const &getPath) : _getPath(getPath) {}
1203 GetPathFn const &_getPath;
1204 bool operator()(IterRef a, SdfPath const &b) const {
1205 return _getPath(a) < b;
1206 }
1207 };
1208
1209 // Search for the path in [begin, end). If present, return it. If not,
1210 // examine prior element in [begin, end). If none, return end. Else, is it
1211 // a prefix of path? If so, return it. Else find common prefix of that
1212 // element and path and recurse.
1213
1214 // If empty sequence, return.
1215 if (begin == end)
1216 return end;
1217
1218 Compare comp(getPath);
1219
1220 // Search for where this path would lexicographically appear in the range.
1221 RandomAccessIterator result = std::lower_bound(begin, end, path, comp);
1222
1223 // If we didn't get the end, check to see if we got the path exactly if
1224 // we're not looking for a strict prefix.
1225 if (!strictPrefix && result != end && getPath(*result) == path) {
1226 return result;
1227 }
1228
1229 // If we got begin (and didn't match in the case of a non-strict prefix)
1230 // then there's no prefix.
1231 if (result == begin) {
1232 return end;
1233 }
1234
1235 // If the prior element is a prefix, we're done.
1236 if (path.HasPrefix(getPath(*--result))) {
1237 return result;
1238 }
1239
1240 // Otherwise, find the common prefix of the lexicographical predecessor and
1241 // look for its prefix in the preceding range.
1242 SdfPath newPath = path.GetCommonPrefix(getPath(*result));
1243 auto origEnd = end;
1244 do {
1245 end = result;
1246 result = std::lower_bound(begin, end, newPath, comp);
1247
1248 if (result != end && getPath(*result) == newPath) {
1249 return result;
1250 }
1251 if (result == begin) {
1252 return origEnd;
1253 }
1254 if (newPath.HasPrefix(getPath(*--result))) {
1255 return result;
1256 }
1257 newPath = newPath.GetCommonPrefix(getPath(*result));
1258 } while (true);
1259}
1260
1268template <class RandomAccessIterator, class GetPathFn = Sdf_PathIdentity,
1269 class = typename std::enable_if<
1270 std::is_base_of<
1271 std::random_access_iterator_tag,
1272 typename std::iterator_traits<
1273 RandomAccessIterator>::iterator_category
1274 >::value
1275 >::type
1276 >
1277RandomAccessIterator
1278SdfPathFindLongestPrefix(RandomAccessIterator begin,
1279 RandomAccessIterator end,
1280 SdfPath const &path,
1281 GetPathFn const &getPath = GetPathFn())
1282{
1283 return Sdf_PathFindLongestPrefixImpl(
1284 begin, end, path, /*strictPrefix=*/false, getPath);
1285}
1286
1294template <class RandomAccessIterator, class GetPathFn = Sdf_PathIdentity,
1295 class = typename std::enable_if<
1296 std::is_base_of<
1297 std::random_access_iterator_tag,
1298 typename std::iterator_traits<
1299 RandomAccessIterator>::iterator_category
1300 >::value
1301 >::type
1302 >
1303RandomAccessIterator
1304SdfPathFindLongestStrictPrefix(RandomAccessIterator begin,
1305 RandomAccessIterator end,
1306 SdfPath const &path,
1307 GetPathFn const &getPath = GetPathFn())
1308{
1309 return Sdf_PathFindLongestPrefixImpl(
1310 begin, end, path, /*strictPrefix=*/true, getPath);
1311}
1312
1313template <class Iter, class MapParam, class GetPathFn = Sdf_PathIdentity>
1314Iter
1315Sdf_PathFindLongestPrefixImpl(
1316 MapParam map, SdfPath const &path, bool strictPrefix,
1317 GetPathFn const &getPath = GetPathFn())
1318{
1319 // Search for the path in map. If present, return it. If not, examine
1320 // prior element in map. If none, return end. Else, is it a prefix of
1321 // path? If so, return it. Else find common prefix of that element and
1322 // path and recurse.
1323
1324 const Iter mapEnd = map.end();
1325
1326 // If empty, return.
1327 if (map.empty())
1328 return mapEnd;
1329
1330 // Search for where this path would lexicographically appear in the range.
1331 Iter result = map.lower_bound(path);
1332
1333 // If we didn't get the end, check to see if we got the path exactly if
1334 // we're not looking for a strict prefix.
1335 if (!strictPrefix && result != mapEnd && getPath(*result) == path)
1336 return result;
1337
1338 // If we got begin (and didn't match in the case of a non-strict prefix)
1339 // then there's no prefix.
1340 if (result == map.begin())
1341 return mapEnd;
1342
1343 // If the prior element is a prefix, we're done.
1344 if (path.HasPrefix(getPath(*--result)))
1345 return result;
1346
1347 // Otherwise, find the common prefix of the lexicographical predecessor and
1348 // recurse looking for it or its longest prefix in the preceding range. We
1349 // always pass strictPrefix=false, since now we're operating on prefixes of
1350 // the original caller's path.
1351 return Sdf_PathFindLongestPrefixImpl<Iter, MapParam>(
1352 map, path.GetCommonPrefix(getPath(*result)), /*strictPrefix=*/false,
1353 getPath);
1354}
1355
1359SDF_API
1360typename std::set<SdfPath>::const_iterator
1361SdfPathFindLongestPrefix(std::set<SdfPath> const &set, SdfPath const &path);
1362
1366template <class T>
1367typename std::map<SdfPath, T>::const_iterator
1368SdfPathFindLongestPrefix(std::map<SdfPath, T> const &map, SdfPath const &path)
1369{
1370 return Sdf_PathFindLongestPrefixImpl<
1371 typename std::map<SdfPath, T>::const_iterator,
1372 std::map<SdfPath, T> const &>(map, path, /*strictPrefix=*/false,
1373 TfGet<0>());
1374}
1375template <class T>
1376typename std::map<SdfPath, T>::iterator
1377SdfPathFindLongestPrefix(std::map<SdfPath, T> &map, SdfPath const &path)
1378{
1379 return Sdf_PathFindLongestPrefixImpl<
1380 typename std::map<SdfPath, T>::iterator,
1381 std::map<SdfPath, T> &>(map, path, /*strictPrefix=*/false,
1382 TfGet<0>());
1383}
1384
1388SDF_API
1389typename std::set<SdfPath>::const_iterator
1390SdfPathFindLongestStrictPrefix(std::set<SdfPath> const &set,
1391 SdfPath const &path);
1392
1396template <class T>
1397typename std::map<SdfPath, T>::const_iterator
1398SdfPathFindLongestStrictPrefix(
1399 std::map<SdfPath, T> const &map, SdfPath const &path)
1400{
1401 return Sdf_PathFindLongestPrefixImpl<
1402 typename std::map<SdfPath, T>::const_iterator,
1403 std::map<SdfPath, T> const &>(map, path, /*strictPrefix=*/true,
1404 TfGet<0>());
1405}
1406template <class T>
1407typename std::map<SdfPath, T>::iterator
1408SdfPathFindLongestStrictPrefix(
1409 std::map<SdfPath, T> &map, SdfPath const &path)
1410{
1411 return Sdf_PathFindLongestPrefixImpl<
1412 typename std::map<SdfPath, T>::iterator,
1413 std::map<SdfPath, T> &>(map, path, /*strictPrefix=*/true,
1414 TfGet<0>());
1415}
1416
1417// A helper function for debugger pretty-printers, etc. This function is *not*
1418// thread-safe. It writes to a static buffer and returns a pointer to it.
1419// Subsequent calls to this function overwrite the memory written in prior
1420// calls. If the given path's string representation exceeds the static buffer
1421// size, return a pointer to a message indicating so.
1422SDF_API
1423char const *
1424Sdf_PathGetDebuggerPathText(SdfPath const &);
1425
1426PXR_NAMESPACE_CLOSE_SCOPE
1427
1428// Sdf_PathNode is not public API, but we need to include it here
1429// so we can inline the ref-counting operations, which must manipulate
1430// its internal _refCount member.
1431#include "pxr/usd/sdf/pathNode.h"
1432
1433#endif // PXR_USD_SDF_PATH_H
Range representing a path and ancestors, and providing methods for iterating over them.
Definition: path.h:1087
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:281
SDF_API SdfPath MakeAbsolutePath(const SdfPath &anchor) const
Returns the absolute form of this path using anchor as the relative basis.
SDF_API SdfPath GetParentPath() const
Return the path that identifies this path's namespace parent.
SDF_API const std::string & GetString() const
Return the string representation of this path as a std::string.
SDF_API bool IsPrimVariantSelectionPath() const
Returns whether the path identifies a variant selection for a prim.
static SDF_API std::string JoinIdentifier(const TfTokenVector &names)
Join names into a single identifier using the namespace delimiter.
static SDF_API bool IsValidIdentifier(const std::string &name)
Returns whether name is a legal identifier for any path component.
SDF_API SdfPath ReplaceTargetPath(const SdfPath &newTargetPath) const
Replaces the relational attribute's target path.
SDF_API void GetAllTargetPathsRecursively(SdfPathVector *result) const
Returns all the relationship target or connection target paths contained in this path,...
SDF_API SdfPath GetPrimOrPrimVariantSelectionPath() const
Creates a path by stripping all relational attributes, targets, and properties, leaving the nearest p...
SDF_API std::pair< SdfPath, SdfPath > RemoveCommonSuffix(const SdfPath &otherPath, bool stopAtRootPrim=false) const
Find and remove the longest common suffix from two paths.
SDF_API SdfPath AppendElementString(const std::string &element) const
Creates a path by extracting and appending an element from the given ascii element encoding.
SDF_API bool IsMapperArgPath() const
Returns whether the path identifies a connection mapper arg.
SDF_API bool IsRelationalAttributePath() const
Returns whether the path identifies a relational attribute.
static SDF_API TfToken StripNamespace(const TfToken &name)
Returns name stripped of any namespaces.
SDF_API bool IsAbsoluteRootOrPrimPath() const
Returns whether the path identifies a prim or the absolute root.
static SDF_API const SdfPath & AbsoluteRootPath()
The absolute path representing the top of the namespace hierarchy.
SDF_API const char * GetText() const
Returns the string representation of this path as a c string.
static SDF_API SdfPathVector GetConciseRelativePaths(const SdfPathVector &paths)
Given some vector of paths, get a vector of concise unambiguous relative paths.
SDF_API std::pair< std::string, std::string > GetVariantSelection() const
Returns the variant selection for this path, if this is a variant selection path.
bool operator<=(const SdfPath &rhs) const
Less than or equal operator.
Definition: path.h:938
SDF_API SdfPath AppendExpression() const
Creates a path by appending an expression element.
SDF_API SdfPath AppendRelationalAttribute(TfToken const &attrName) const
Creates a path by appending an element for attrName to this path.
SDF_API std::string GetElementString() const
Returns an ascii representation of the "terminal" element of this path, which can be used to reconstr...
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
Definition: path.h:405
SDF_API bool IsAbsolutePath() const
Returns whether the path is absolute.
SDF_API SdfPath GetAbsoluteRootOrPrimPath() const
Creates a path by stripping all properties and relational attributes from this path,...
SDF_API SdfPath AppendPath(const SdfPath &newSuffix) const
Creates a path by appending a given relative path to this path.
SDF_API SdfPath MakeRelativePath(const SdfPath &anchor) const
Returns the relative form of this path using anchor as the relative basis.
static SDF_API const SdfPath & ReflexiveRelativePath()
The relative path representing "self".
bool operator>(const SdfPath &rhs) const
Greater than operator.
Definition: path.h:932
static SDF_API std::string JoinIdentifier(const std::string &lhs, const std::string &rhs)
Join lhs and rhs into a single identifier using the namespace delimiter.
static SDF_API std::vector< std::string > TokenizeIdentifier(const std::string &name)
Tokenizes name by the namespace delimiter.
SDF_API bool IsPropertyPath() const
Returns whether the path identifies a property.
SDF_API SdfPath AppendMapper(const SdfPath &targetPath) const
Creates a path by appending a mapper element for targetPath.
SDF_API SdfPath AppendElementToken(const TfToken &elementTok) const
Like AppendElementString() but take the element as a TfToken.
SDF_API bool HasPrefix(const SdfPath &prefix) const
Return true if both this path and prefix are not the empty path and this path has prefix as a prefix.
static SDF_API std::string JoinIdentifier(const std::vector< std::string > &names)
Join names into a single identifier using the namespace delimiter.
SDF_API bool IsTargetPath() const
Returns whether the path identifies a relationship or connection target.
SDF_API size_t GetPathElementCount() const
Returns the number of path elements in this path.
SDF_API TfToken GetElementToken() const
Like GetElementString() but return the value as a TfToken.
static SDF_API const SdfPath & EmptyPath()
The empty path value, equivalent to SdfPath().
SDF_API const std::string & GetName() const
Returns the name of the prim, property or relational attribute identified by the path.
SDF_API TfToken GetAsToken() const
Return the string representation of this path as a TfToken.
SDF_API const SdfPath & GetTargetPath() const
Returns the relational attribute or mapper target path for this path.
SDF_API SdfPathVector GetPrefixes() const
Returns the prefix paths of this path.
static SDF_API std::string StripNamespace(const std::string &name)
Returns name stripped of any namespaces.
SDF_API void GetPrefixes(SdfPathVector *prefixes, size_t numPrefixes) const
Fill prefixes with up to numPrefixes prefixes of this path.
static SDF_API TfTokenVector TokenizeIdentifierAsTokens(const std::string &name)
Tokenizes name by the namespace delimiter.
SDF_API bool IsRootPrimPath() const
Returns whether the path identifies a root prim.
static SDF_API bool IsValidNamespacedIdentifier(const std::string &name)
Returns whether name is a legal namespaced identifier.
SDF_API const TfToken & GetNameToken() const
Returns the name of the prim, property or relational attribute identified by the path,...
SDF_API bool IsPrimPath() const
Returns whether the path identifies a prim.
static SDF_API std::pair< std::string, bool > StripPrefixNamespace(const std::string &name, const std::string &matchNamespace)
Returns (name, true) where name is stripped of the prefix specified by matchNamespace if name indeed ...
SDF_API SdfPath AppendVariantSelection(const std::string &variantSet, const std::string &variant) const
Creates a path by appending an element for variantSet and variant to this path.
SDF_API SdfPath AppendProperty(TfToken const &propName) const
Creates a path by appending an element for propName to this path.
SDF_API bool IsExpressionPath() const
Returns whether the path identifies a connection expression.
SDF_API bool IsNamespacedPropertyPath() const
Returns whether the path identifies a namespaced property.
SDF_API SdfPath AppendMapperArg(TfToken const &argName) const
Creates a path by appending an element for argName.
SDF_API TfToken const & GetToken() const
Return the string representation of this path as a TfToken lvalue.
bool operator<(const SdfPath &rhs) const
Comparison operator.
Definition: path.h:919
bool operator>=(const SdfPath &rhs) const
Greater than or equal operator.
Definition: path.h:944
SDF_API SdfPath AppendChild(TfToken const &childName) const
Creates a path by appending an element for childName to this path.
bool ContainsPropertyElements() const
Return true if this path contains any property elements, false otherwise.
Definition: path.h:378
SDF_API bool IsMapperPath() const
Returns whether the path identifies a connection mapper.
static SDF_API void RemoveDescendentPaths(SdfPathVector *paths)
Remove all elements of paths that are prefixed by other elements in paths.
SDF_API SdfPath GetCommonPrefix(const SdfPath &path) const
Returns a path with maximal length that is a prefix path of both this path and path.
static SDF_API std::string JoinIdentifier(const TfToken &lhs, const TfToken &rhs)
Join lhs and rhs into a single identifier using the namespace delimiter.
static SDF_API bool IsValidPathString(const std::string &pathString, std::string *errMsg=0)
Return true if pathString is a valid path string, meaning that passing the string to the SdfPath cons...
SDF_API SdfPath ReplacePrefix(const SdfPath &oldPrefix, const SdfPath &newPrefix, bool fixTargetPaths=true) const
Returns a path with all occurrences of the prefix path oldPrefix replaced with the prefix path newPre...
SDF_API TfSpan< SdfPath > GetPrefixes(TfSpan< SdfPath > prefixes) const
Fill prefixes with up to prefixes.size() prefixes of this path.
SDF_API bool IsAbsoluteRootPath() const
Return true if this path is the AbsoluteRootPath().
bool operator==(const SdfPath &rhs) const
Equality operator.
Definition: path.h:906
SDF_API SdfPathAncestorsRange GetAncestorsRange() const
Return a range for iterating over the ancestors of this path.
SDF_API bool ContainsPrimVariantSelection() const
Returns whether the path or any of its parent paths identifies a variant selection for a prim.
SDF_API bool IsPrimPropertyPath() const
Returns whether the path identifies a prim's property.
SDF_API SdfPath StripAllVariantSelections() const
Create a path by stripping all variant selections from all components of this path,...
SDF_API bool ContainsTargetPath() const
Return true if this path is or has a prefix that's a target path or a mapper path.
SDF_API SdfPath ReplaceName(TfToken const &newName) const
Return a copy of this path with its final component changed to newName.
SDF_API void GetPrefixes(SdfPathVector *prefixes) const
Fills prefixes with prefixes of this path.
SDF_API bool IsPrimOrPrimVariantSelectionPath() const
Return true if this path is a prim path or is a prim variant selection path.
SDF_API SdfPath AppendTarget(const SdfPath &targetPath) const
Creates a path by appending an element for targetPath.
SdfPath() noexcept=default
Constructs the default, empty path.
SDF_API SdfPathVector GetPrefixes(size_t numPrefixes) const
Return up to numPrefixes prefix paths of this path.
SDF_API SdfPath GetPrimPath() const
Creates a path by stripping all relational attributes, targets, properties, and variant selections fr...
static SDF_API void RemoveAncestorPaths(SdfPathVector *paths)
Remove all elements of paths that prefix other elements in paths.
bool operator!=(const SdfPath &rhs) const
Inequality operator.
Definition: path.h:911
SDF_API std::string GetAsString() const
Return the string representation of this path as a std::string.
Stores a pointer to a ValueType which uses TfDelegatedCountIncrement and TfDelegatedCountDecrement to...
Function object for retrieving the N'th element of a std::pair or std::tuple.
Definition: stl.h:362
A user-extensible hashing mechanism for use with runtime hash tables.
Definition: hash.h:472
Represents a range of contiguous elements.
Definition: span.h:71
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:71
GF_API std::ostream & operator<<(std::ostream &, const GfBBox3d &)
Output a GfBBox3d using the format [(range) matrix zeroArea].
STL namespace.
TfToken class for efficient string referencing and hashing, plus conversions to and from stl string c...
std::vector< TfToken > TfTokenVector
Convenience types.
Definition: token.h:440