Loading...
Searching...
No Matches
path.h
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/delegatedCountPtr.h"
33#include "pxr/base/tf/stl.h"
34#include "pxr/base/tf/token.h"
35#include "pxr/base/vt/traits.h"
36
37#include <algorithm>
38#include <iterator>
39#include <set>
40#include <string>
41#include <type_traits>
42#include <utility>
43#include <vector>
44
45PXR_NAMESPACE_OPEN_SCOPE
46
47class Sdf_PathNode;
49
50// Ref-counting pointer to a path node.
51// Delegated ref-counts are used to keep the size of SdfPath
52// the same as a raw pointer. (shared_ptr, by comparison,
53// is the size of two pointers.)
54
56
57void TfDelegatedCountIncrement(Sdf_PathNode const *) noexcept;
58void TfDelegatedCountDecrement(Sdf_PathNode const *) noexcept;
59
60// Tags used for the pools of path nodes.
61struct Sdf_PathPrimTag;
62struct Sdf_PathPropTag;
63
64// These are validated below.
65static constexpr size_t Sdf_SizeofPrimPathNode = sizeof(void *) * 3;
66static constexpr size_t Sdf_SizeofPropPathNode = sizeof(void *) * 3;
67
68using Sdf_PathPrimPartPool = Sdf_Pool<
69 Sdf_PathPrimTag, Sdf_SizeofPrimPathNode, /*regionBits=*/8>;
70
71using Sdf_PathPropPartPool = Sdf_Pool<
72 Sdf_PathPropTag, Sdf_SizeofPropPathNode, /*regionBits=*/8>;
73
74using Sdf_PathPrimHandle = Sdf_PathPrimPartPool::Handle;
75using Sdf_PathPropHandle = Sdf_PathPropPartPool::Handle;
76
77// This handle class wraps up the raw Prim/PropPartPool handles.
78template <class Handle, bool Counted, class PathNode=Sdf_PathNode const>
79struct Sdf_PathNodeHandleImpl {
80private:
81 typedef Sdf_PathNodeHandleImpl this_type;
82
83public:
84 static constexpr bool IsCounted = Counted;
85
86 constexpr Sdf_PathNodeHandleImpl() noexcept {};
87
88 explicit
89 Sdf_PathNodeHandleImpl(Sdf_PathNode const *p, bool add_ref = true)
90 : _poolHandle(Handle::GetHandle(reinterpret_cast<char const *>(p))) {
91 if (p && add_ref) {
92 _AddRef(p);
93 }
94 }
95
96 explicit
97 Sdf_PathNodeHandleImpl(Handle h, bool add_ref = true)
98 : _poolHandle(h) {
99 if (h && add_ref) {
100 _AddRef();
101 }
102 }
103
104 Sdf_PathNodeHandleImpl(Sdf_PathNodeHandleImpl const &rhs) noexcept
105 : _poolHandle(rhs._poolHandle) {
106 if (_poolHandle) {
107 _AddRef();
108 }
109 }
110
111 ~Sdf_PathNodeHandleImpl() {
112 if (_poolHandle) {
113 _DecRef();
114 }
115 }
116
117 Sdf_PathNodeHandleImpl &
118 operator=(Sdf_PathNodeHandleImpl const &rhs) {
119 if (Counted && *this == rhs) {
120 return *this;
121 }
122 this_type(rhs).swap(*this);
123 return *this;
124 }
125
126 Sdf_PathNodeHandleImpl(Sdf_PathNodeHandleImpl &&rhs) noexcept
127 : _poolHandle(rhs._poolHandle) {
128 rhs._poolHandle = nullptr;
129 }
130
131 Sdf_PathNodeHandleImpl &
132 operator=(Sdf_PathNodeHandleImpl &&rhs) noexcept {
133 this_type(std::move(rhs)).swap(*this);
134 return *this;
135 }
136
137 Sdf_PathNodeHandleImpl &
138 operator=(Sdf_PathNode const *rhs) noexcept {
139 this_type(rhs).swap(*this);
140 return *this;
141 }
142
143 void reset() noexcept {
144 _poolHandle = Handle { nullptr };
145 }
146
147 inline Sdf_PathNode const *
148 get() const noexcept {
149 return reinterpret_cast<Sdf_PathNode *>(_poolHandle.GetPtr());
150 }
151
152 Sdf_PathNode const &
153 operator*() const {
154 return *get();
155 }
156
157 Sdf_PathNode const *
158 operator->() const {
159 return get();
160 }
161
162 explicit operator bool() const noexcept {
163 return static_cast<bool>(_poolHandle);
164 }
165
166 void swap(Sdf_PathNodeHandleImpl &rhs) noexcept {
167 _poolHandle.swap(rhs._poolHandle);
168 }
169
170 inline bool operator==(Sdf_PathNodeHandleImpl const &rhs) const noexcept {
171 return _poolHandle == rhs._poolHandle;
172 }
173 inline bool operator!=(Sdf_PathNodeHandleImpl const &rhs) const noexcept {
174 return _poolHandle != rhs._poolHandle;
175 }
176 inline bool operator<(Sdf_PathNodeHandleImpl const &rhs) const noexcept {
177 return _poolHandle < rhs._poolHandle;
178 }
179private:
180
181 inline void _AddRef(Sdf_PathNode const *p) const {
182 if (Counted) {
183 TfDelegatedCountIncrement(p);
184 }
185 }
186
187 inline void _AddRef() const {
188 _AddRef(get());
189 }
190
191 inline void _DecRef() const {
192 if (Counted) {
193 TfDelegatedCountDecrement(get());
194 }
195 }
196
197 Handle _poolHandle { nullptr };
198};
199
200using Sdf_PathPrimNodeHandle =
201 Sdf_PathNodeHandleImpl<Sdf_PathPrimHandle, /*Counted=*/true>;
202
203using Sdf_PathPropNodeHandle =
204 Sdf_PathNodeHandleImpl<Sdf_PathPropHandle, /*Counted=*/false>;
205
206
208typedef std::set<class SdfPath> SdfPathSet;
210typedef std::vector<class SdfPath> SdfPathVector;
211
212// Tell VtValue that SdfPath is cheap to copy.
213VT_TYPE_IS_CHEAP_TO_COPY(class SdfPath);
214
290{
291public:
293 SDF_API static const SdfPath & EmptyPath();
294
297 SDF_API static const SdfPath & AbsoluteRootPath();
298
300 SDF_API static const SdfPath & ReflexiveRelativePath();
301
304
307 SdfPath() noexcept = default;
308
321 //
322 // XXX We may want to revisit the behavior when constructing
323 // a path with an empty string ("") to accept it without error and
324 // return EmptyPath.
325 SDF_API explicit SdfPath(const std::string &path);
326
328
331
333 SDF_API size_t GetPathElementCount() const;
334
336 SDF_API bool IsAbsolutePath() const;
337
339 SDF_API bool IsAbsoluteRootPath() const;
340
342 SDF_API bool IsPrimPath() const;
343
345 SDF_API bool IsAbsoluteRootOrPrimPath() const;
346
351 SDF_API bool IsRootPrimPath() const;
352
358 SDF_API bool IsPropertyPath() const;
359
363 SDF_API bool IsPrimPropertyPath() const;
364
368 SDF_API bool IsNamespacedPropertyPath() const;
369
372 SDF_API bool IsPrimVariantSelectionPath() const;
373
377
380 SDF_API bool ContainsPrimVariantSelection() const;
381
388 return static_cast<bool>(_propPart);
389 }
390
393 SDF_API bool ContainsTargetPath() const;
394
398 SDF_API bool IsRelationalAttributePath() const;
399
402 SDF_API bool IsTargetPath() const;
403
405 SDF_API bool IsMapperPath() const;
406
408 SDF_API bool IsMapperArgPath() const;
409
411 SDF_API bool IsExpressionPath() const;
412
414 inline bool IsEmpty() const noexcept {
415 // No need to check _propPart, because it can only be non-null if
416 // _primPart is non-null.
417 return !_primPart;
418 }
419
425 SDF_API TfToken GetAsToken() const;
426
436 SDF_API TfToken const &GetToken() const;
437
443 SDF_API std::string GetAsString() const;
444
454 SDF_API const std::string &GetString() const;
455
466 SDF_API const char *GetText() const;
467
475 SDF_API SdfPathVector GetPrefixes() const;
476
485 SDF_API SdfPathVector GetPrefixes(size_t numPrefixes) const;
486
496 SDF_API void GetPrefixes(SdfPathVector *prefixes) const;
497
506 SDF_API void GetPrefixes(SdfPathVector *prefixes, size_t numPrefixes) const;
507
514
525 SDF_API const std::string &GetName() const;
526
529 SDF_API const TfToken &GetNameToken() const;
530
548 SDF_API std::string GetElementString() const;
549
551 SDF_API TfToken GetElementToken() const;
552
572 SDF_API SdfPath ReplaceName(TfToken const &newName) const;
573
586 SDF_API const SdfPath &GetTargetPath() const;
587
595 SDF_API void GetAllTargetPathsRecursively(SdfPathVector *result) const;
596
601 SDF_API
602 std::pair<std::string, std::string> GetVariantSelection() const;
603
606 SDF_API bool HasPrefix( const SdfPath &prefix ) const;
607
609
612
635 SDF_API SdfPath GetParentPath() const;
636
644 SDF_API SdfPath GetPrimPath() const;
645
655
662
667
675 SDF_API SdfPath AppendPath(const SdfPath &newSuffix) const;
676
682 SDF_API SdfPath AppendChild(TfToken const &childName) const;
683
688 SDF_API SdfPath AppendProperty(TfToken const &propName) const;
689
694 SDF_API
695 SdfPath AppendVariantSelection(const std::string &variantSet,
696 const std::string &variant) const;
697
702 SDF_API SdfPath AppendTarget(const SdfPath &targetPath) const;
703
708 SDF_API
710
714 SDF_API
715 SdfPath ReplaceTargetPath( const SdfPath &newTargetPath ) const;
716
721 SDF_API SdfPath AppendMapper(const SdfPath &targetPath) const;
722
727 SDF_API SdfPath AppendMapperArg(TfToken const &argName) const;
728
732 SDF_API SdfPath AppendExpression() const;
733
743 SDF_API SdfPath AppendElementString(const std::string &element) const;
744
746 SDF_API SdfPath AppendElementToken(const TfToken &elementTok) const;
747
757 SDF_API
758 SdfPath ReplacePrefix(const SdfPath &oldPrefix,
759 const SdfPath &newPrefix,
760 bool fixTargetPaths=true) const;
761
764 SDF_API SdfPath GetCommonPrefix(const SdfPath &path) const;
765
781 SDF_API
782 std::pair<SdfPath, SdfPath>
783 RemoveCommonSuffix(const SdfPath& otherPath,
784 bool stopAtRootPrim = false) const;
785
795 SDF_API SdfPath MakeAbsolutePath(const SdfPath & anchor) const;
796
809 SDF_API SdfPath MakeRelativePath(const SdfPath & anchor) const;
810
812
815
818 SDF_API static bool IsValidIdentifier(const std::string &name);
819
822 SDF_API static bool IsValidNamespacedIdentifier(const std::string &name);
823
827 SDF_API static std::vector<std::string> TokenizeIdentifier(const std::string &name);
828
832 SDF_API
833 static TfTokenVector TokenizeIdentifierAsTokens(const std::string &name);
834
837 SDF_API
838 static std::string JoinIdentifier(const std::vector<std::string> &names);
839
842 SDF_API
843 static std::string JoinIdentifier(const TfTokenVector& names);
844
849 SDF_API
850 static std::string JoinIdentifier(const std::string &lhs,
851 const std::string &rhs);
852
857 SDF_API
858 static std::string JoinIdentifier(const TfToken &lhs, const TfToken &rhs);
859
863 SDF_API
864 static std::string StripNamespace(const std::string &name);
865
869 SDF_API
870 static TfToken StripNamespace(const TfToken &name);
871
880 SDF_API
881 static std::pair<std::string, bool>
882 StripPrefixNamespace(const std::string &name,
883 const std::string &matchNamespace);
884
889 SDF_API
890 static bool IsValidPathString(const std::string &pathString,
891 std::string *errMsg = 0);
892
894
897
899 inline bool operator==(const SdfPath &rhs) const {
900 return _AsInt() == rhs._AsInt();
901 }
902
904 inline bool operator!=(const SdfPath &rhs) const {
905 return !(*this == rhs);
906 }
907
912 inline bool operator<(const SdfPath &rhs) const {
913 if (_AsInt() == rhs._AsInt()) {
914 return false;
915 }
916 if (!_primPart || !rhs._primPart) {
917 return !_primPart && rhs._primPart;
918 }
919 // Valid prim parts -- must walk node structure, etc.
920 return _LessThanInternal(*this, rhs);
921 }
922
925 inline bool operator>(const SdfPath& rhs) const {
926 return rhs < *this;
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 !(*this < rhs);
939 }
940
941 template <class HashState>
942 friend void TfHashAppend(HashState &h, SdfPath const &path) {
943 // The hash function is pretty sensitive performance-wise. Be
944 // careful making changes here, and run tests.
945 uint32_t primPart, propPart;
946 memcpy(&primPart, &path._primPart, sizeof(primPart));
947 memcpy(&propPart, &path._propPart, sizeof(propPart));
948 h.Append(primPart);
949 h.Append(propPart);
950 }
951
952 // For hash maps and sets
953 struct Hash {
954 inline size_t operator()(const SdfPath& path) const {
955 return TfHash()(path);
956 }
957 };
958
959 inline size_t GetHash() const {
960 return Hash()(*this);
961 }
962
963 // For cases where an unspecified total order that is not stable from
964 // run-to-run is needed.
965 struct FastLessThan {
966 inline bool operator()(const SdfPath& a, const SdfPath& b) const {
967 return a._AsInt() < b._AsInt();
968 }
969 };
970
972
975
982 SDF_API static SdfPathVector
983 GetConciseRelativePaths(const SdfPathVector& paths);
984
988 SDF_API static void RemoveDescendentPaths(SdfPathVector *paths);
989
992 SDF_API static void RemoveAncestorPaths(SdfPathVector *paths);
993
995
996private:
997
998 // This is used for all internal path construction where we do operations
999 // via nodes and then want to return a new path with a resulting prim and
1000 // property parts.
1001
1002 // Accept rvalues.
1003 explicit SdfPath(Sdf_PathPrimNodeHandle &&primNode)
1004 : _primPart(std::move(primNode)) {}
1005
1006 SdfPath(Sdf_PathPrimNodeHandle &&primPart,
1007 Sdf_PathPropNodeHandle &&propPart)
1008 : _primPart(std::move(primPart))
1009 , _propPart(std::move(propPart)) {}
1010
1011 // Construct from prim & prop parts.
1012 SdfPath(Sdf_PathPrimNodeHandle const &primPart,
1013 Sdf_PathPropNodeHandle const &propPart)
1014 : _primPart(primPart)
1015 , _propPart(propPart) {}
1016
1017 // Construct from prim & prop node pointers.
1018 SdfPath(Sdf_PathNode const *primPart,
1019 Sdf_PathNode const *propPart)
1020 : _primPart(primPart)
1021 , _propPart(propPart) {}
1022
1023 friend class Sdf_PathNode;
1024 friend class Sdfext_PathAccess;
1025 friend class SdfPathAncestorsRange;
1026
1027 // converts elements to a string for parsing (unfortunate)
1028 static std::string
1029 _ElementsToString(bool absolute, const std::vector<std::string> &elements);
1030
1031 SdfPath _ReplacePrimPrefix(SdfPath const &oldPrefix,
1032 SdfPath const &newPrefix) const;
1033
1034 SdfPath _ReplaceTargetPathPrefixes(SdfPath const &oldPrefix,
1035 SdfPath const &newPrefix) const;
1036
1037 SdfPath _ReplacePropPrefix(SdfPath const &oldPrefix,
1038 SdfPath const &newPrefix,
1039 bool fixTargetPaths) const;
1040
1041 // Helper to implement the uninlined portion of operator<.
1042 SDF_API static bool
1043 _LessThanInternal(SdfPath const &lhs, SdfPath const &rhs);
1044
1045 inline uint64_t _AsInt() const {
1046 static_assert(sizeof(*this) == sizeof(uint64_t), "");
1047 uint64_t ret;
1048 std::memcpy(&ret, this, sizeof(*this));
1049 return ret;
1050 }
1051
1052 friend void swap(SdfPath &lhs, SdfPath &rhs) {
1053 lhs._primPart.swap(rhs._primPart);
1054 lhs._propPart.swap(rhs._propPart);
1055 }
1056
1057 SDF_API friend char const *
1058 Sdf_PathGetDebuggerPathText(SdfPath const &);
1059
1060 Sdf_PathPrimNodeHandle _primPart;
1061 Sdf_PathPropNodeHandle _propPart;
1062
1063};
1064
1065
1083{
1084public:
1085
1086 SdfPathAncestorsRange(const SdfPath& path)
1087 : _path(path) {}
1088
1089 const SdfPath& GetPath() const { return _path; }
1090
1091 struct iterator {
1092 using iterator_category = std::forward_iterator_tag;
1093 using value_type = SdfPath;
1094 using difference_type = std::ptrdiff_t;
1095 using reference = const SdfPath&;
1096 using pointer = const SdfPath*;
1097
1098 iterator(const SdfPath& path) : _path(path) {}
1099
1100 iterator() = default;
1101
1102 SDF_API
1103 iterator& operator++();
1104
1105 const SdfPath& operator*() const { return _path; }
1106
1107 const SdfPath* operator->() const { return &_path; }
1108
1109 bool operator==(const iterator& o) const { return _path == o._path; }
1110
1111 bool operator!=(const iterator& o) const { return _path != o._path; }
1112
1116 SDF_API friend difference_type
1117 distance(const iterator& first, const iterator& last);
1118
1119 private:
1120 SdfPath _path;
1121 };
1122
1123 iterator begin() const { return iterator(_path); }
1124
1125 iterator end() const { return iterator(); }
1126
1127private:
1128 SdfPath _path;
1129};
1130
1131
1132// Overload hash_value for SdfPath. Used by things like boost::hash.
1133inline size_t hash_value(SdfPath const &path)
1134{
1135 return path.GetHash();
1136}
1137
1139SDF_API std::ostream & operator<<( std::ostream &out, const SdfPath &path );
1140
1141// Helper for SdfPathFindPrefixedRange & SdfPathFindLongestPrefix. A function
1142// object that returns an SdfPath const & unchanged.
1143struct Sdf_PathIdentity {
1144 inline SdfPath const &operator()(SdfPath const &arg) const {
1145 return arg;
1146 }
1147};
1148
1155template <class ForwardIterator, class GetPathFn = Sdf_PathIdentity>
1156std::pair<ForwardIterator, ForwardIterator>
1157SdfPathFindPrefixedRange(ForwardIterator begin, ForwardIterator end,
1158 SdfPath const &prefix,
1159 GetPathFn const &getPath = GetPathFn()) {
1160 using IterRef =
1161 typename std::iterator_traits<ForwardIterator>::reference;
1162
1163 struct Compare {
1164 Compare(GetPathFn const &getPath) : _getPath(getPath) {}
1165 GetPathFn const &_getPath;
1166 bool operator()(IterRef a, SdfPath const &b) const {
1167 return _getPath(a) < b;
1168 }
1169 };
1170
1171 std::pair<ForwardIterator, ForwardIterator> result;
1172
1173 // First, use lower_bound to find where \a prefix would go.
1174 result.first = std::lower_bound(begin, end, prefix, Compare(getPath));
1175
1176 // Next, find end of range starting from the lower bound, using the
1177 // prefixing condition to define the boundary.
1178 result.second = TfFindBoundary(result.first, end,
1179 [&prefix, &getPath](IterRef iterRef) {
1180 return getPath(iterRef).HasPrefix(prefix);
1181 });
1182
1183 return result;
1184}
1185
1186template <class RandomAccessIterator, class GetPathFn>
1187RandomAccessIterator
1188Sdf_PathFindLongestPrefixImpl(RandomAccessIterator begin,
1189 RandomAccessIterator end,
1190 SdfPath const &path,
1191 bool strictPrefix,
1192 GetPathFn const &getPath)
1193{
1194 using IterRef =
1195 typename std::iterator_traits<RandomAccessIterator>::reference;
1196
1197 struct Compare {
1198 Compare(GetPathFn const &getPath) : _getPath(getPath) {}
1199 GetPathFn const &_getPath;
1200 bool operator()(IterRef a, SdfPath const &b) const {
1201 return _getPath(a) < b;
1202 }
1203 };
1204
1205 // Search for the path in [begin, end). If present, return it. If not,
1206 // examine prior element in [begin, end). If none, return end. Else, is it
1207 // a prefix of path? If so, return it. Else find common prefix of that
1208 // element and path and recurse.
1209
1210 // If empty sequence, return.
1211 if (begin == end)
1212 return end;
1213
1214 Compare comp(getPath);
1215
1216 // Search for where this path would lexicographically appear in the range.
1217 RandomAccessIterator result = std::lower_bound(begin, end, path, comp);
1218
1219 // If we didn't get the end, check to see if we got the path exactly if
1220 // we're not looking for a strict prefix.
1221 if (!strictPrefix && result != end && getPath(*result) == path) {
1222 return result;
1223 }
1224
1225 // If we got begin (and didn't match in the case of a non-strict prefix)
1226 // then there's no prefix.
1227 if (result == begin) {
1228 return end;
1229 }
1230
1231 // If the prior element is a prefix, we're done.
1232 if (path.HasPrefix(getPath(*--result))) {
1233 return result;
1234 }
1235
1236 // Otherwise, find the common prefix of the lexicographical predecessor and
1237 // look for its prefix in the preceding range.
1238 SdfPath newPath = path.GetCommonPrefix(getPath(*result));
1239 auto origEnd = end;
1240 do {
1241 end = result;
1242 result = std::lower_bound(begin, end, newPath, comp);
1243
1244 if (result != end && getPath(*result) == newPath) {
1245 return result;
1246 }
1247 if (result == begin) {
1248 return origEnd;
1249 }
1250 if (newPath.HasPrefix(getPath(*--result))) {
1251 return result;
1252 }
1253 newPath = newPath.GetCommonPrefix(getPath(*result));
1254 } while (true);
1255}
1256
1264template <class RandomAccessIterator, class GetPathFn = Sdf_PathIdentity,
1265 class = typename std::enable_if<
1266 std::is_base_of<
1267 std::random_access_iterator_tag,
1268 typename std::iterator_traits<
1269 RandomAccessIterator>::iterator_category
1270 >::value
1271 >::type
1272 >
1273RandomAccessIterator
1274SdfPathFindLongestPrefix(RandomAccessIterator begin,
1275 RandomAccessIterator end,
1276 SdfPath const &path,
1277 GetPathFn const &getPath = GetPathFn())
1278{
1279 return Sdf_PathFindLongestPrefixImpl(
1280 begin, end, path, /*strictPrefix=*/false, getPath);
1281}
1282
1290template <class RandomAccessIterator, class GetPathFn = Sdf_PathIdentity,
1291 class = typename std::enable_if<
1292 std::is_base_of<
1293 std::random_access_iterator_tag,
1294 typename std::iterator_traits<
1295 RandomAccessIterator>::iterator_category
1296 >::value
1297 >::type
1298 >
1299RandomAccessIterator
1300SdfPathFindLongestStrictPrefix(RandomAccessIterator begin,
1301 RandomAccessIterator end,
1302 SdfPath const &path,
1303 GetPathFn const &getPath = GetPathFn())
1304{
1305 return Sdf_PathFindLongestPrefixImpl(
1306 begin, end, path, /*strictPrefix=*/true, getPath);
1307}
1308
1309template <class Iter, class MapParam, class GetPathFn = Sdf_PathIdentity>
1310Iter
1311Sdf_PathFindLongestPrefixImpl(
1312 MapParam map, SdfPath const &path, bool strictPrefix,
1313 GetPathFn const &getPath = GetPathFn())
1314{
1315 // Search for the path in map. If present, return it. If not, examine
1316 // prior element in map. If none, return end. Else, is it a prefix of
1317 // path? If so, return it. Else find common prefix of that element and
1318 // path and recurse.
1319
1320 const Iter mapEnd = map.end();
1321
1322 // If empty, return.
1323 if (map.empty())
1324 return mapEnd;
1325
1326 // Search for where this path would lexicographically appear in the range.
1327 Iter result = map.lower_bound(path);
1328
1329 // If we didn't get the end, check to see if we got the path exactly if
1330 // we're not looking for a strict prefix.
1331 if (!strictPrefix && result != mapEnd && getPath(*result) == path)
1332 return result;
1333
1334 // If we got begin (and didn't match in the case of a non-strict prefix)
1335 // then there's no prefix.
1336 if (result == map.begin())
1337 return mapEnd;
1338
1339 // If the prior element is a prefix, we're done.
1340 if (path.HasPrefix(getPath(*--result)))
1341 return result;
1342
1343 // Otherwise, find the common prefix of the lexicographical predecessor and
1344 // recurse looking for it or its longest prefix in the preceding range. We
1345 // always pass strictPrefix=false, since now we're operating on prefixes of
1346 // the original caller's path.
1347 return Sdf_PathFindLongestPrefixImpl<Iter, MapParam>(
1348 map, path.GetCommonPrefix(getPath(*result)), /*strictPrefix=*/false,
1349 getPath);
1350}
1351
1355SDF_API
1356typename std::set<SdfPath>::const_iterator
1357SdfPathFindLongestPrefix(std::set<SdfPath> const &set, SdfPath const &path);
1358
1362template <class T>
1363typename std::map<SdfPath, T>::const_iterator
1364SdfPathFindLongestPrefix(std::map<SdfPath, T> const &map, SdfPath const &path)
1365{
1366 return Sdf_PathFindLongestPrefixImpl<
1367 typename std::map<SdfPath, T>::const_iterator,
1368 std::map<SdfPath, T> const &>(map, path, /*strictPrefix=*/false,
1369 TfGet<0>());
1370}
1371template <class T>
1372typename std::map<SdfPath, T>::iterator
1373SdfPathFindLongestPrefix(std::map<SdfPath, T> &map, SdfPath const &path)
1374{
1375 return Sdf_PathFindLongestPrefixImpl<
1376 typename std::map<SdfPath, T>::iterator,
1377 std::map<SdfPath, T> &>(map, path, /*strictPrefix=*/false,
1378 TfGet<0>());
1379}
1380
1384SDF_API
1385typename std::set<SdfPath>::const_iterator
1386SdfPathFindLongestStrictPrefix(std::set<SdfPath> const &set,
1387 SdfPath const &path);
1388
1392template <class T>
1393typename std::map<SdfPath, T>::const_iterator
1394SdfPathFindLongestStrictPrefix(
1395 std::map<SdfPath, T> const &map, SdfPath const &path)
1396{
1397 return Sdf_PathFindLongestPrefixImpl<
1398 typename std::map<SdfPath, T>::const_iterator,
1399 std::map<SdfPath, T> const &>(map, path, /*strictPrefix=*/true,
1400 TfGet<0>());
1401}
1402template <class T>
1403typename std::map<SdfPath, T>::iterator
1404SdfPathFindLongestStrictPrefix(
1405 std::map<SdfPath, T> &map, SdfPath const &path)
1406{
1407 return Sdf_PathFindLongestPrefixImpl<
1408 typename std::map<SdfPath, T>::iterator,
1409 std::map<SdfPath, T> &>(map, path, /*strictPrefix=*/true,
1410 TfGet<0>());
1411}
1412
1413// A helper function for debugger pretty-printers, etc. This function is *not*
1414// thread-safe. It writes to a static buffer and returns a pointer to it.
1415// Subsequent calls to this function overwrite the memory written in prior
1416// calls. If the given path's string representation exceeds the static buffer
1417// size, return a pointer to a message indicating so.
1418SDF_API
1419char const *
1420Sdf_PathGetDebuggerPathText(SdfPath const &);
1421
1422PXR_NAMESPACE_CLOSE_SCOPE
1423
1424// Sdf_PathNode is not public API, but we need to include it here
1425// so we can inline the ref-counting operations, which must manipulate
1426// its internal _refCount member.
1427#include "pxr/usd/sdf/pathNode.h"
1428
1429PXR_NAMESPACE_OPEN_SCOPE
1430
1431static_assert(Sdf_SizeofPrimPathNode == sizeof(Sdf_PrimPathNode), "");
1432static_assert(Sdf_SizeofPropPathNode == sizeof(Sdf_PrimPropertyPathNode), "");
1433
1434PXR_NAMESPACE_CLOSE_SCOPE
1435
1436#endif // PXR_USD_SDF_PATH_H
Range representing a path and ancestors, and providing methods for iterating over them.
Definition: path.h:1083
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:290
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:931
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:414
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:925
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:912
bool operator>=(const SdfPath &rhs) const
Greater than or equal operator.
Definition: path.h:937
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:387
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 bool IsAbsoluteRootPath() const
Return true if this path is the AbsoluteRootPath().
bool operator==(const SdfPath &rhs) const
Equality operator.
Definition: path.h:899
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:904
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:379
A user-extensible hashing mechanism for use with runtime hash tables.
Definition: hash.h:477
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:88
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:457