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// These are validated below.
49
50#ifdef ARCH_BITS_32
51static constexpr size_t Sdf_SizeofPrimPathNode = 16;
52static constexpr size_t Sdf_SizeofPropPathNode = 16;
53#else
54static constexpr size_t Sdf_SizeofPrimPathNode = 24;
55static constexpr size_t Sdf_SizeofPropPathNode = 24;
56#endif
57
58using Sdf_PathPrimPartPool = Sdf_Pool<
59 Sdf_PathPrimTag, Sdf_SizeofPrimPathNode, /*regionBits=*/8>;
60
61using Sdf_PathPropPartPool = Sdf_Pool<
62 Sdf_PathPropTag, Sdf_SizeofPropPathNode, /*regionBits=*/8>;
63
64using Sdf_PathPrimHandle = Sdf_PathPrimPartPool::Handle;
65using Sdf_PathPropHandle = Sdf_PathPropPartPool::Handle;
66
67// This handle class wraps up the raw Prim/PropPartPool handles.
68template <class Handle, bool Counted, class PathNode=Sdf_PathNode const>
69struct Sdf_PathNodeHandleImpl {
70private:
71 typedef Sdf_PathNodeHandleImpl this_type;
72
73public:
74 static constexpr bool IsCounted = Counted;
75
76 constexpr Sdf_PathNodeHandleImpl() noexcept {};
77
78 explicit
79 Sdf_PathNodeHandleImpl(Sdf_PathNode const *p, bool add_ref = true)
80 : _poolHandle(Handle::GetHandle(reinterpret_cast<char const *>(p))) {
81 if (p && add_ref) {
82 _AddRef(p);
83 }
84 }
85
86 explicit
87 Sdf_PathNodeHandleImpl(Handle h, bool add_ref = true)
88 : _poolHandle(h) {
89 if (h && add_ref) {
90 _AddRef();
91 }
92 }
93
94 Sdf_PathNodeHandleImpl(Sdf_PathNodeHandleImpl const &rhs) noexcept
95 : _poolHandle(rhs._poolHandle) {
96 if (_poolHandle) {
97 _AddRef();
98 }
99 }
100
101 ~Sdf_PathNodeHandleImpl() {
102 if (_poolHandle) {
103 _DecRef();
104 }
105 }
106
107 Sdf_PathNodeHandleImpl &
108 operator=(Sdf_PathNodeHandleImpl const &rhs) {
109 if (Counted && *this == rhs) {
110 return *this;
111 }
112 this_type(rhs).swap(*this);
113 return *this;
114 }
115
116 Sdf_PathNodeHandleImpl(Sdf_PathNodeHandleImpl &&rhs) noexcept
117 : _poolHandle(rhs._poolHandle) {
118 rhs._poolHandle = nullptr;
119 }
120
121 Sdf_PathNodeHandleImpl &
122 operator=(Sdf_PathNodeHandleImpl &&rhs) noexcept {
123 this_type(std::move(rhs)).swap(*this);
124 return *this;
125 }
126
127 Sdf_PathNodeHandleImpl &
128 operator=(Sdf_PathNode const *rhs) noexcept {
129 this_type(rhs).swap(*this);
130 return *this;
131 }
132
133 void reset() noexcept {
134 _poolHandle = Handle { nullptr };
135 }
136
137 inline Sdf_PathNode const *
138 get() const noexcept {
139 return reinterpret_cast<Sdf_PathNode *>(_poolHandle.GetPtr());
140 }
141
142 Sdf_PathNode const &
143 operator*() const {
144 return *get();
145 }
146
147 Sdf_PathNode const *
148 operator->() const {
149 return get();
150 }
151
152 explicit operator bool() const noexcept {
153 return static_cast<bool>(_poolHandle);
154 }
155
156 void swap(Sdf_PathNodeHandleImpl &rhs) noexcept {
157 _poolHandle.swap(rhs._poolHandle);
158 }
159
160 inline bool operator==(Sdf_PathNodeHandleImpl const &rhs) const noexcept {
161 return _poolHandle == rhs._poolHandle;
162 }
163 inline bool operator!=(Sdf_PathNodeHandleImpl const &rhs) const noexcept {
164 return _poolHandle != rhs._poolHandle;
165 }
166 inline bool operator<(Sdf_PathNodeHandleImpl const &rhs) const noexcept {
167 return _poolHandle < rhs._poolHandle;
168 }
169private:
170
171 inline void _AddRef(Sdf_PathNode const *p) const {
172 if (Counted) {
173 TfDelegatedCountIncrement(p);
174 }
175 }
176
177 inline void _AddRef() const {
178 _AddRef(get());
179 }
180
181 inline void _DecRef() const {
182 if (Counted) {
183 TfDelegatedCountDecrement(get());
184 }
185 }
186
187 Handle _poolHandle { nullptr };
188};
189
190using Sdf_PathPrimNodeHandle =
191 Sdf_PathNodeHandleImpl<Sdf_PathPrimHandle, /*Counted=*/true>;
192
193using Sdf_PathPropNodeHandle =
194 Sdf_PathNodeHandleImpl<Sdf_PathPropHandle, /*Counted=*/false>;
195
196
198typedef std::set<class SdfPath> SdfPathSet;
200typedef std::vector<class SdfPath> SdfPathVector;
201
202// Tell VtValue that SdfPath is cheap to copy.
203VT_TYPE_IS_CHEAP_TO_COPY(class SdfPath);
204
280{
281public:
283 SDF_API static const SdfPath & EmptyPath();
284
287 SDF_API static const SdfPath & AbsoluteRootPath();
288
290 SDF_API static const SdfPath & ReflexiveRelativePath();
291
294
297 SdfPath() noexcept = default;
298
311 //
312 // XXX We may want to revisit the behavior when constructing
313 // a path with an empty string ("") to accept it without error and
314 // return EmptyPath.
315 SDF_API explicit SdfPath(const std::string &path);
316
318
321
323 SDF_API size_t GetPathElementCount() const;
324
326 SDF_API bool IsAbsolutePath() const;
327
329 SDF_API bool IsAbsoluteRootPath() const;
330
332 SDF_API bool IsPrimPath() const;
333
335 SDF_API bool IsAbsoluteRootOrPrimPath() const;
336
341 SDF_API bool IsRootPrimPath() const;
342
348 SDF_API bool IsPropertyPath() const;
349
353 SDF_API bool IsPrimPropertyPath() const;
354
358 SDF_API bool IsNamespacedPropertyPath() const;
359
362 SDF_API bool IsPrimVariantSelectionPath() const;
363
367
370 SDF_API bool ContainsPrimVariantSelection() const;
371
378 return static_cast<bool>(_propPart);
379 }
380
383 SDF_API bool ContainsTargetPath() const;
384
388 SDF_API bool IsRelationalAttributePath() const;
389
392 SDF_API bool IsTargetPath() const;
393
395 SDF_API bool IsMapperPath() const;
396
398 SDF_API bool IsMapperArgPath() const;
399
401 SDF_API bool IsExpressionPath() const;
402
404 inline bool IsEmpty() const noexcept {
405 // No need to check _propPart, because it can only be non-null if
406 // _primPart is non-null.
407 return !_primPart;
408 }
409
415 SDF_API TfToken GetAsToken() const;
416
426 SDF_API TfToken const &GetToken() const;
427
433 SDF_API std::string GetAsString() const;
434
444 SDF_API const std::string &GetString() const;
445
456 SDF_API const char *GetText() const;
457
465 SDF_API SdfPathVector GetPrefixes() const;
466
475 SDF_API SdfPathVector GetPrefixes(size_t numPrefixes) const;
476
486 SDF_API void GetPrefixes(SdfPathVector *prefixes) const;
487
496 SDF_API void GetPrefixes(SdfPathVector *prefixes, size_t numPrefixes) const;
497
511
520
531 SDF_API const std::string &GetName() const;
532
535 SDF_API const TfToken &GetNameToken() const;
536
554 SDF_API std::string GetElementString() const;
555
557 SDF_API TfToken GetElementToken() const;
558
578 SDF_API SdfPath ReplaceName(TfToken const &newName) const;
579
592 SDF_API const SdfPath &GetTargetPath() const;
593
601 SDF_API void GetAllTargetPathsRecursively(SdfPathVector *result) const;
602
607 SDF_API
608 std::pair<std::string, std::string> GetVariantSelection() const;
609
612 SDF_API bool HasPrefix( const SdfPath &prefix ) const;
613
615
618
641 SDF_API SdfPath GetParentPath() const;
642
650 SDF_API SdfPath GetPrimPath() const;
651
661
668
673
681 SDF_API SdfPath AppendPath(const SdfPath &newSuffix) const;
682
688 SDF_API SdfPath AppendChild(TfToken const &childName) const;
689
694 SDF_API SdfPath AppendProperty(TfToken const &propName) const;
695
700 SDF_API
701 SdfPath AppendVariantSelection(const std::string &variantSet,
702 const std::string &variant) const;
703
708 SDF_API SdfPath AppendTarget(const SdfPath &targetPath) const;
709
714 SDF_API
716
720 SDF_API
721 SdfPath ReplaceTargetPath( const SdfPath &newTargetPath ) const;
722
727 SDF_API SdfPath AppendMapper(const SdfPath &targetPath) const;
728
733 SDF_API SdfPath AppendMapperArg(TfToken const &argName) const;
734
738 SDF_API SdfPath AppendExpression() const;
739
749 SDF_API SdfPath AppendElementString(const std::string &element) const;
750
752 SDF_API SdfPath AppendElementToken(const TfToken &elementTok) const;
753
763 SDF_API
764 SdfPath ReplacePrefix(const SdfPath &oldPrefix,
765 const SdfPath &newPrefix,
766 bool fixTargetPaths=true) const;
767
770 SDF_API SdfPath GetCommonPrefix(const SdfPath &path) const;
771
787 SDF_API
788 std::pair<SdfPath, SdfPath>
789 RemoveCommonSuffix(const SdfPath& otherPath,
790 bool stopAtRootPrim = false) const;
791
801 SDF_API SdfPath MakeAbsolutePath(const SdfPath & anchor) const;
802
815 SDF_API SdfPath MakeRelativePath(const SdfPath & anchor) const;
816
818
821
824 SDF_API static bool IsValidIdentifier(const std::string &name);
825
828 SDF_API static bool IsValidNamespacedIdentifier(const std::string &name);
829
833 SDF_API static std::vector<std::string> TokenizeIdentifier(const std::string &name);
834
838 SDF_API
839 static TfTokenVector TokenizeIdentifierAsTokens(const std::string &name);
840
843 SDF_API
844 static std::string JoinIdentifier(const std::vector<std::string> &names);
845
848 SDF_API
849 static std::string JoinIdentifier(const TfTokenVector& names);
850
855 SDF_API
856 static std::string JoinIdentifier(const std::string &lhs,
857 const std::string &rhs);
858
863 SDF_API
864 static std::string JoinIdentifier(const TfToken &lhs, const TfToken &rhs);
865
869 SDF_API
870 static std::string StripNamespace(const std::string &name);
871
875 SDF_API
876 static TfToken StripNamespace(const TfToken &name);
877
886 SDF_API
887 static std::pair<std::string, bool>
888 StripPrefixNamespace(const std::string &name,
889 const std::string &matchNamespace);
890
895 SDF_API
896 static bool IsValidPathString(const std::string &pathString,
897 std::string *errMsg = 0);
898
900
903
905 inline bool operator==(const SdfPath &rhs) const {
906 return _AsInt() == rhs._AsInt();
907 }
908
910 inline bool operator!=(const SdfPath &rhs) const {
911 return !(*this == rhs);
912 }
913
918 inline bool operator<(const SdfPath &rhs) const {
919 if (_AsInt() == rhs._AsInt()) {
920 return false;
921 }
922 if (!_primPart || !rhs._primPart) {
923 return !_primPart && rhs._primPart;
924 }
925 // Valid prim parts -- must walk node structure, etc.
926 return _LessThanInternal(*this, rhs);
927 }
928
931 inline bool operator>(const SdfPath& rhs) const {
932 return rhs < *this;
933 }
934
937 inline bool operator<=(const SdfPath& rhs) const {
938 return !(rhs < *this);
939 }
940
943 inline bool operator>=(const SdfPath& rhs) const {
944 return !(*this < rhs);
945 }
946
947 template <class HashState>
948 friend void TfHashAppend(HashState &h, SdfPath const &path) {
949 // The hash function is pretty sensitive performance-wise. Be
950 // careful making changes here, and run tests.
951 uint32_t primPart, propPart;
952 memcpy(&primPart, &path._primPart, sizeof(primPart));
953 memcpy(&propPart, &path._propPart, sizeof(propPart));
954 h.Append(primPart);
955 h.Append(propPart);
956 }
957
958 // For hash maps and sets
959 struct Hash {
960 inline size_t operator()(const SdfPath& path) const {
961 return TfHash()(path);
962 }
963 };
964
965 inline size_t GetHash() const {
966 return Hash()(*this);
967 }
968
969 // For cases where an unspecified total order that is not stable from
970 // run-to-run is needed.
971 struct FastLessThan {
972 inline bool operator()(const SdfPath& a, const SdfPath& b) const {
973 return a._AsInt() < b._AsInt();
974 }
975 };
976
978
981
988 SDF_API static SdfPathVector
989 GetConciseRelativePaths(const SdfPathVector& paths);
990
994 SDF_API static void RemoveDescendentPaths(SdfPathVector *paths);
995
998 SDF_API static void RemoveAncestorPaths(SdfPathVector *paths);
999
1001
1002private:
1003
1004 // This is used for all internal path construction where we do operations
1005 // via nodes and then want to return a new path with a resulting prim and
1006 // property parts.
1007
1008 // Accept rvalues.
1009 explicit SdfPath(Sdf_PathPrimNodeHandle &&primNode)
1010 : _primPart(std::move(primNode)) {}
1011
1012 SdfPath(Sdf_PathPrimNodeHandle &&primPart,
1013 Sdf_PathPropNodeHandle &&propPart)
1014 : _primPart(std::move(primPart))
1015 , _propPart(std::move(propPart)) {}
1016
1017 // Construct from prim & prop parts.
1018 SdfPath(Sdf_PathPrimNodeHandle const &primPart,
1019 Sdf_PathPropNodeHandle const &propPart)
1020 : _primPart(primPart)
1021 , _propPart(propPart) {}
1022
1023 // Construct from prim & prop node pointers.
1024 SdfPath(Sdf_PathNode const *primPart,
1025 Sdf_PathNode const *propPart)
1026 : _primPart(primPart)
1027 , _propPart(propPart) {}
1028
1029 friend class Sdf_PathNode;
1030 friend class Sdfext_PathAccess;
1031 friend class SdfPathAncestorsRange;
1032 friend class Sdf_PathInitAccess;
1033
1034 SdfPath _ReplacePrimPrefix(SdfPath const &oldPrefix,
1035 SdfPath const &newPrefix) const;
1036
1037 SdfPath _ReplaceTargetPathPrefixes(SdfPath const &oldPrefix,
1038 SdfPath const &newPrefix) const;
1039
1040 SdfPath _ReplacePropPrefix(SdfPath const &oldPrefix,
1041 SdfPath const &newPrefix,
1042 bool fixTargetPaths) const;
1043
1044 // Helper to implement the uninlined portion of operator<.
1045 SDF_API static bool
1046 _LessThanInternal(SdfPath const &lhs, SdfPath const &rhs);
1047
1048 inline uint64_t _AsInt() const {
1049 static_assert(sizeof(*this) == sizeof(uint64_t), "");
1050 uint64_t ret;
1051 std::memcpy(&ret, this, sizeof(*this));
1052 return ret;
1053 }
1054
1055 friend void swap(SdfPath &lhs, SdfPath &rhs) {
1056 lhs._primPart.swap(rhs._primPart);
1057 lhs._propPart.swap(rhs._propPart);
1058 }
1059
1060 SDF_API friend char const *
1061 Sdf_PathGetDebuggerPathText(SdfPath const &);
1062
1063 Sdf_PathPrimNodeHandle _primPart;
1064 Sdf_PathPropNodeHandle _propPart;
1065
1066};
1067
1068
1086{
1087public:
1088
1089 SdfPathAncestorsRange(const SdfPath& path)
1090 : _path(path) {}
1091
1092 const SdfPath& GetPath() const { return _path; }
1093
1094 struct iterator {
1095 using iterator_category = std::forward_iterator_tag;
1096 using value_type = SdfPath;
1097 using difference_type = std::ptrdiff_t;
1098 using reference = const SdfPath&;
1099 using pointer = const SdfPath*;
1100
1101 iterator(const SdfPath& path) : _path(path) {}
1102
1103 iterator() = default;
1104
1105 SDF_API
1106 iterator& operator++();
1107
1108 const SdfPath& operator*() const { return _path; }
1109
1110 const SdfPath* operator->() const { return &_path; }
1111
1112 bool operator==(const iterator& o) const { return _path == o._path; }
1113
1114 bool operator!=(const iterator& o) const { return _path != o._path; }
1115
1119 SDF_API friend difference_type
1120 distance(const iterator& first, const iterator& last);
1121
1122 private:
1123 SdfPath _path;
1124 };
1125
1126 iterator begin() const { return iterator(_path); }
1127
1128 iterator end() const { return iterator(); }
1129
1130private:
1131 SdfPath _path;
1132};
1133
1134
1135// Overload hash_value for SdfPath. Used by things like boost::hash.
1136inline size_t hash_value(SdfPath const &path)
1137{
1138 return path.GetHash();
1139}
1140
1142SDF_API std::ostream & operator<<( std::ostream &out, const SdfPath &path );
1143
1144// Helper for SdfPathFindPrefixedRange & SdfPathFindLongestPrefix. A function
1145// object that returns an SdfPath const & unchanged.
1146struct Sdf_PathIdentity {
1147 inline SdfPath const &operator()(SdfPath const &arg) const {
1148 return arg;
1149 }
1150};
1151
1158template <class ForwardIterator, class GetPathFn = Sdf_PathIdentity>
1159std::pair<ForwardIterator, ForwardIterator>
1160SdfPathFindPrefixedRange(ForwardIterator begin, ForwardIterator end,
1161 SdfPath const &prefix,
1162 GetPathFn const &getPath = GetPathFn()) {
1163 using IterRef =
1164 typename std::iterator_traits<ForwardIterator>::reference;
1165
1166 struct Compare {
1167 Compare(GetPathFn const &getPath) : _getPath(getPath) {}
1168 GetPathFn const &_getPath;
1169 bool operator()(IterRef a, SdfPath const &b) const {
1170 return _getPath(a) < b;
1171 }
1172 };
1173
1174 std::pair<ForwardIterator, ForwardIterator> result;
1175
1176 // First, use lower_bound to find where \a prefix would go.
1177 result.first = std::lower_bound(begin, end, prefix, Compare(getPath));
1178
1179 // Next, find end of range starting from the lower bound, using the
1180 // prefixing condition to define the boundary.
1181 result.second = TfFindBoundary(result.first, end,
1182 [&prefix, &getPath](IterRef iterRef) {
1183 return getPath(iterRef).HasPrefix(prefix);
1184 });
1185
1186 return result;
1187}
1188
1189template <class RandomAccessIterator, class GetPathFn>
1190RandomAccessIterator
1191Sdf_PathFindLongestPrefixImpl(RandomAccessIterator begin,
1192 RandomAccessIterator end,
1193 SdfPath const &path,
1194 bool strictPrefix,
1195 GetPathFn const &getPath)
1196{
1197 using IterRef =
1198 typename std::iterator_traits<RandomAccessIterator>::reference;
1199
1200 struct Compare {
1201 Compare(GetPathFn const &getPath) : _getPath(getPath) {}
1202 GetPathFn const &_getPath;
1203 bool operator()(IterRef a, SdfPath const &b) const {
1204 return _getPath(a) < b;
1205 }
1206 };
1207
1208 // Search for the path in [begin, end). If present, return it. If not,
1209 // examine prior element in [begin, end). If none, return end. Else, is it
1210 // a prefix of path? If so, return it. Else find common prefix of that
1211 // element and path and recurse.
1212
1213 // If empty sequence, return.
1214 if (begin == end)
1215 return end;
1216
1217 Compare comp(getPath);
1218
1219 // Search for where this path would lexicographically appear in the range.
1220 RandomAccessIterator result = std::lower_bound(begin, end, path, comp);
1221
1222 // If we didn't get the end, check to see if we got the path exactly if
1223 // we're not looking for a strict prefix.
1224 if (!strictPrefix && result != end && getPath(*result) == path) {
1225 return result;
1226 }
1227
1228 // If we got begin (and didn't match in the case of a non-strict prefix)
1229 // then there's no prefix.
1230 if (result == begin) {
1231 return end;
1232 }
1233
1234 // If the prior element is a prefix, we're done.
1235 if (path.HasPrefix(getPath(*--result))) {
1236 return result;
1237 }
1238
1239 // Otherwise, find the common prefix of the lexicographical predecessor and
1240 // look for its prefix in the preceding range.
1241 SdfPath newPath = path.GetCommonPrefix(getPath(*result));
1242 auto origEnd = end;
1243 do {
1244 end = result;
1245 result = std::lower_bound(begin, end, newPath, comp);
1246
1247 if (result != end && getPath(*result) == newPath) {
1248 return result;
1249 }
1250 if (result == begin) {
1251 return origEnd;
1252 }
1253 if (newPath.HasPrefix(getPath(*--result))) {
1254 return result;
1255 }
1256 newPath = newPath.GetCommonPrefix(getPath(*result));
1257 } while (true);
1258}
1259
1267template <class RandomAccessIterator, class GetPathFn = Sdf_PathIdentity,
1268 class = typename std::enable_if<
1269 std::is_base_of<
1270 std::random_access_iterator_tag,
1271 typename std::iterator_traits<
1272 RandomAccessIterator>::iterator_category
1273 >::value
1274 >::type
1275 >
1276RandomAccessIterator
1277SdfPathFindLongestPrefix(RandomAccessIterator begin,
1278 RandomAccessIterator end,
1279 SdfPath const &path,
1280 GetPathFn const &getPath = GetPathFn())
1281{
1282 return Sdf_PathFindLongestPrefixImpl(
1283 begin, end, path, /*strictPrefix=*/false, getPath);
1284}
1285
1293template <class RandomAccessIterator, class GetPathFn = Sdf_PathIdentity,
1294 class = typename std::enable_if<
1295 std::is_base_of<
1296 std::random_access_iterator_tag,
1297 typename std::iterator_traits<
1298 RandomAccessIterator>::iterator_category
1299 >::value
1300 >::type
1301 >
1302RandomAccessIterator
1303SdfPathFindLongestStrictPrefix(RandomAccessIterator begin,
1304 RandomAccessIterator end,
1305 SdfPath const &path,
1306 GetPathFn const &getPath = GetPathFn())
1307{
1308 return Sdf_PathFindLongestPrefixImpl(
1309 begin, end, path, /*strictPrefix=*/true, getPath);
1310}
1311
1312template <class Iter, class MapParam, class GetPathFn = Sdf_PathIdentity>
1313Iter
1314Sdf_PathFindLongestPrefixImpl(
1315 MapParam map, SdfPath const &path, bool strictPrefix,
1316 GetPathFn const &getPath = GetPathFn())
1317{
1318 // Search for the path in map. If present, return it. If not, examine
1319 // prior element in map. If none, return end. Else, is it a prefix of
1320 // path? If so, return it. Else find common prefix of that element and
1321 // path and recurse.
1322
1323 const Iter mapEnd = map.end();
1324
1325 // If empty, return.
1326 if (map.empty())
1327 return mapEnd;
1328
1329 // Search for where this path would lexicographically appear in the range.
1330 Iter result = map.lower_bound(path);
1331
1332 // If we didn't get the end, check to see if we got the path exactly if
1333 // we're not looking for a strict prefix.
1334 if (!strictPrefix && result != mapEnd && getPath(*result) == path)
1335 return result;
1336
1337 // If we got begin (and didn't match in the case of a non-strict prefix)
1338 // then there's no prefix.
1339 if (result == map.begin())
1340 return mapEnd;
1341
1342 // If the prior element is a prefix, we're done.
1343 if (path.HasPrefix(getPath(*--result)))
1344 return result;
1345
1346 // Otherwise, find the common prefix of the lexicographical predecessor and
1347 // recurse looking for it or its longest prefix in the preceding range. We
1348 // always pass strictPrefix=false, since now we're operating on prefixes of
1349 // the original caller's path.
1350 return Sdf_PathFindLongestPrefixImpl<Iter, MapParam>(
1351 map, path.GetCommonPrefix(getPath(*result)), /*strictPrefix=*/false,
1352 getPath);
1353}
1354
1358SDF_API
1359typename std::set<SdfPath>::const_iterator
1360SdfPathFindLongestPrefix(std::set<SdfPath> const &set, SdfPath const &path);
1361
1365template <class T>
1366typename std::map<SdfPath, T>::const_iterator
1367SdfPathFindLongestPrefix(std::map<SdfPath, T> const &map, SdfPath const &path)
1368{
1369 return Sdf_PathFindLongestPrefixImpl<
1370 typename std::map<SdfPath, T>::const_iterator,
1371 std::map<SdfPath, T> const &>(map, path, /*strictPrefix=*/false,
1372 TfGet<0>());
1373}
1374template <class T>
1375typename std::map<SdfPath, T>::iterator
1376SdfPathFindLongestPrefix(std::map<SdfPath, T> &map, SdfPath const &path)
1377{
1378 return Sdf_PathFindLongestPrefixImpl<
1379 typename std::map<SdfPath, T>::iterator,
1380 std::map<SdfPath, T> &>(map, path, /*strictPrefix=*/false,
1381 TfGet<0>());
1382}
1383
1387SDF_API
1388typename std::set<SdfPath>::const_iterator
1389SdfPathFindLongestStrictPrefix(std::set<SdfPath> const &set,
1390 SdfPath const &path);
1391
1395template <class T>
1396typename std::map<SdfPath, T>::const_iterator
1397SdfPathFindLongestStrictPrefix(
1398 std::map<SdfPath, T> const &map, SdfPath const &path)
1399{
1400 return Sdf_PathFindLongestPrefixImpl<
1401 typename std::map<SdfPath, T>::const_iterator,
1402 std::map<SdfPath, T> const &>(map, path, /*strictPrefix=*/true,
1403 TfGet<0>());
1404}
1405template <class T>
1406typename std::map<SdfPath, T>::iterator
1407SdfPathFindLongestStrictPrefix(
1408 std::map<SdfPath, T> &map, SdfPath const &path)
1409{
1410 return Sdf_PathFindLongestPrefixImpl<
1411 typename std::map<SdfPath, T>::iterator,
1412 std::map<SdfPath, T> &>(map, path, /*strictPrefix=*/true,
1413 TfGet<0>());
1414}
1415
1416// A helper function for debugger pretty-printers, etc. This function is *not*
1417// thread-safe. It writes to a static buffer and returns a pointer to it.
1418// Subsequent calls to this function overwrite the memory written in prior
1419// calls. If the given path's string representation exceeds the static buffer
1420// size, return a pointer to a message indicating so.
1421SDF_API
1422char const *
1423Sdf_PathGetDebuggerPathText(SdfPath const &);
1424
1425PXR_NAMESPACE_CLOSE_SCOPE
1426
1427// Sdf_PathNode is not public API, but we need to include it here
1428// so we can inline the ref-counting operations, which must manipulate
1429// its internal _refCount member.
1430#include "pxr/usd/sdf/pathNode.h"
1431
1432PXR_NAMESPACE_OPEN_SCOPE
1433
1434static_assert(Sdf_SizeofPrimPathNode == sizeof(Sdf_PrimPathNode), "");
1435static_assert(Sdf_SizeofPropPathNode == sizeof(Sdf_PrimPropertyPathNode), "");
1436
1437PXR_NAMESPACE_CLOSE_SCOPE
1438
1439#endif // PXR_USD_SDF_PATH_H
Range representing a path and ancestors, and providing methods for iterating over them.
Definition: path.h:1086
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:280
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:937
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:404
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:931
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:918
bool operator>=(const SdfPath &rhs) const
Greater than or equal operator.
Definition: path.h:943
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:377
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:905
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:910
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