24 #ifndef PXR_USD_SDF_PATH_TABLE_H 25 #define PXR_USD_SDF_PATH_TABLE_H 28 #include "pxr/usd/sdf/api.h" 29 #include "pxr/usd/sdf/path.h" 30 #include "pxr/base/tf/pointerAndBits.h" 31 #include "pxr/base/tf/functionRef.h" 33 #include <boost/iterator/iterator_facade.hpp> 34 #include <boost/noncopyable.hpp> 40 PXR_NAMESPACE_OPEN_SCOPE
44 void Sdf_VisitPathTableInParallel(
void **,
size_t,
TfFunctionRef<
void(
void*&)>);
84 template <
class MappedType>
90 typedef MappedType mapped_type;
91 typedef std::pair<key_type, mapped_type> value_type;
99 struct _Entry : boost::noncopyable {
100 _Entry(value_type
const &value, _Entry *n)
104 , nextSiblingOrParent(0,
false) {}
108 _Entry *GetNextSibling() {
109 return nextSiblingOrParent.template BitsAs<bool>() ?
110 nextSiblingOrParent.Get() : 0;
114 _Entry
const *GetNextSibling()
const {
115 return nextSiblingOrParent.template BitsAs<bool>() ?
116 nextSiblingOrParent.Get() : 0;
121 _Entry *GetParentLink() {
122 return nextSiblingOrParent.template BitsAs<bool>() ? 0 :
123 nextSiblingOrParent.Get();
127 _Entry
const *GetParentLink()
const {
128 return nextSiblingOrParent.template BitsAs<bool>() ? 0 :
129 nextSiblingOrParent.Get();
134 void SetSibling(_Entry *sibling) {
135 nextSiblingOrParent.Set(sibling,
true);
140 void SetParentLink(_Entry *parent) {
141 nextSiblingOrParent.Set(parent,
false);
145 void AddChild(_Entry *child) {
149 child->SetSibling(firstChild);
151 child->SetParentLink(
this);
155 void RemoveChild(_Entry *child) {
157 if (child == firstChild) {
158 firstChild = child->GetNextSibling();
162 _Entry *prev, *cur = firstChild;
165 cur = prev->GetNextSibling();
166 }
while (cur != child);
167 prev->nextSiblingOrParent = cur->nextSiblingOrParent;
190 typedef std::vector<_Entry *> _BucketVec;
196 template <
class,
class>
friend class Iterator;
197 template <
class ValType,
class EntryPtr>
199 public boost::iterator_facade<Iterator<ValType, EntryPtr>,
200 ValType, boost::forward_traversal_tag>
208 template <
class OtherVal,
class OtherEntryPtr>
209 Iterator(Iterator<OtherVal, OtherEntryPtr>
const &other)
210 : _entry(other._entry)
216 Iterator GetNextSubtree()
const {
219 if (EntryPtr sibling = _entry->GetNextSibling()) {
221 result._entry = sibling;
225 for (EntryPtr p = _entry->GetParentLink(); p;
226 p = p->GetParentLink()) {
227 if (EntryPtr sibling = p->GetNextSibling()) {
228 result._entry = sibling;
239 bool HasChild()
const {
240 return bool(_entry->firstChild);
244 friend class boost::iterator_core_access;
246 template <
class,
class>
friend class Iterator;
248 explicit Iterator(EntryPtr entry)
256 inline void increment() {
258 _entry = _entry->firstChild ? _entry->firstChild :
259 GetNextSubtree()._entry;
264 template <
class OtherVal,
class OtherEntryPtr>
265 bool equal(Iterator<OtherVal, OtherEntryPtr>
const &other)
const {
266 return _entry == other._entry;
270 ValType &dereference()
const {
271 return _entry->value;
278 typedef Iterator<value_type, _Entry *> iterator;
279 typedef Iterator<const value_type, const _Entry *> const_iterator;
289 : _buckets(other._buckets.
size())
295 for (const_iterator i = other.
begin(),
end = other.
end();
297 iterator j = _InsertInTable(*i).first;
299 if (i._entry->firstChild && !j._entry->firstChild) {
300 j._entry->firstChild =
301 _InsertInTable(i._entry->firstChild->value).first._entry;
304 if (i._entry->nextSiblingOrParent.Get() &&
305 !j._entry->nextSiblingOrParent.Get()) {
306 j._entry->nextSiblingOrParent.Set(
307 _InsertInTable(i._entry->nextSiblingOrParent.
308 Get()->value).first._entry,
309 i._entry->nextSiblingOrParent.template BitsAs<bool>());
316 : _buckets(std::move(other._buckets))
366 const_iterator
end()
const {
367 return const_iterator(0);
377 iterator i =
find(path);
393 _Entry *
const entry = i._entry;
394 _EraseSubtree(entry);
395 _RemoveFromParent(entry);
396 _EraseFromTable(entry);
404 for (_Entry *e = _buckets[_Hash(path)]; e; e = e->next) {
405 if (e->value.first == path)
417 for (_Entry
const *e = _buckets[_Hash(path)]; e; e = e->next) {
418 if (e->value.first == path)
419 return const_iterator(e);
428 std::pair<iterator, iterator>
430 std::pair<iterator, iterator> result;
431 result.first =
find(path);
432 result.second = result.first.GetNextSubtree();
439 std::pair<const_iterator, const_iterator>
441 std::pair<const_iterator, const_iterator> result;
442 result.first =
find(path);
443 result.second = result.first.GetNextSubtree();
453 inline size_t size()
const {
return _size; }
474 _Entry *
const newEntry = result.first._entry;
475 SdfPath const &parentPath = _GetParentPath(value.first);
478 insert(value_type(parentPath, mapped_type())).first;
480 parIter._entry->AddChild(newEntry);
491 return insert(value_type(path, mapped_type())).first->second;
500 for (
size_t i = 0, n = _buckets.size(); i != n; ++i) {
501 _Entry *entry = _buckets[i];
503 _Entry *next = entry->next;
516 [](
void*& voidEntry) {
517 _Entry *entry = static_cast<_Entry *>(voidEntry);
519 _Entry *next = entry->next;
525 Sdf_VisitPathTableInParallel(reinterpret_cast<void **>(_buckets.data()),
526 _buckets.size(), visitFn);
532 _buckets.swap(other._buckets);
539 std::vector<size_t> sizes(_buckets.size(), 0u);;
540 for (
size_t i = 0, n = _buckets.size(); i != n; ++i) {
541 for (_Entry *entry = _buckets[i]; entry; entry = entry->next) {
559 for (iterator i=range.first; i!=range.second; ++i) {
561 i->first.ReplacePrefix(oldName, newName),
565 if (range.first != range.second)
574 template <
typename Callback>
577 [&visitFn](
void*& voidEntry) {
578 _Entry *entry = static_cast<_Entry *>(voidEntry);
580 visitFn(std::cref(entry->value.first),
581 std::ref(entry->value.second));
585 Sdf_VisitPathTableInParallel(reinterpret_cast<void **>(_buckets.data()),
586 _buckets.size(), lambda);
591 template <
typename Callback>
594 [&visitFn](
void*& voidEntry) {
595 const _Entry *entry = static_cast<const _Entry *>(voidEntry);
597 visitFn(std::cref(entry->value.first),
598 std::cref(entry->value.second));
602 Sdf_VisitPathTableInParallel(
604 reinterpret_cast<void **>(const_cast<_Entry**>(_buckets.data())),
605 _buckets.size(), lambda);
625 _Entry **bucketHead = &(_buckets[_Hash(value.first)]);
626 for (_Entry *e = *bucketHead; e; e = e->next)
627 if (e->value.first == value.first)
634 bucketHead = &(_buckets[_Hash(value.first)]);
641 *bucketHead =
new _Entry(value, *bucketHead);
651 void _EraseFromTable(_Entry *entry) {
653 _Entry **cur = &_buckets[_Hash(entry->value.first)];
654 while (*cur != entry)
655 cur = &((*cur)->next);
665 void _EraseSubtree(_Entry *entry) {
667 if (_Entry *
const firstChild = entry->firstChild) {
668 _EraseSubtreeAndSiblings(firstChild);
669 _EraseFromTable(firstChild);
675 void _EraseSubtreeAndSiblings(_Entry *entry) {
677 _EraseSubtree(entry);
680 _Entry *sibling = entry->GetNextSibling();
681 _Entry *nextSibling = sibling ? sibling->GetNextSibling() :
nullptr;
683 _EraseSubtree(sibling);
684 _EraseFromTable(sibling);
685 sibling = nextSibling;
686 nextSibling = sibling ? sibling->GetNextSibling() :
nullptr;
692 void _RemoveFromParent(_Entry *entry) {
697 iterator parIter =
find(_GetParentPath(entry->value.first));
700 parIter._entry->RemoveChild(entry);
712 _mask = std::max(
size_t(7), (_mask << 1) + 1);
713 _BucketVec newBuckets(_mask + 1);
716 for (
size_t i = 0, n = _buckets.size(); i != n; ++i) {
717 _Entry *elem = _buckets[i];
720 _Entry *next = elem->next;
723 _Entry *&m = newBuckets[_Hash(elem->value.first)];
735 _buckets.swap(newBuckets);
739 bool _IsTooFull()
const {
740 return _size > _buckets.size();
744 inline size_t _Hash(
SdfPath const &path)
const {
745 return path.GetHash() & _mask;
755 PXR_NAMESPACE_CLOSE_SCOPE
757 #endif // PXR_USD_SDF_PATH_TABLE_H const_iterator end() const
Return a const_iterator denoting the end of the table.
size_t size() const
Return the number of elements in the table.
void UpdateForRename(const SdfPath &oldName, const SdfPath &newName)
Replaces all prefixes from oldName to newName.
SdfPathTable & operator=(SdfPathTable &&other)
Move assignment.
size_t count(SdfPath const &path) const
Return 1 if there is an element for path in the table, otherwise 0.
~SdfPathTable()
Destructor.
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
SdfPathTable & operator=(SdfPathTable const &other)
Copy assignment.
mapped_type & operator[](SdfPath const &path)
Shorthand for the following, where t is an SdfPathTable<T>.
const_iterator find(SdfPath const &path) const
Return a const_iterator to the element corresponding to path, or end() if there is none.
std::pair< iterator, bool > _IterBoolPair
Result type for insert().
SDF_API SdfPath GetParentPath() const
Return the path that identifies this path's namespace parent.
This class provides a non-owning reference to a type-erased callable object with a specified signatur...
SdfPathTable(SdfPathTable const &other)
Copy constructor.
void ParallelForEach(Callback const &visitFn) const
ParallelForEach: const version, runnable on a const path table and taking a (const SdfPath&,...
SdfPathTable(SdfPathTable &&other)
Move constructor.
std::pair< const_iterator, const_iterator > FindSubtreeRange(SdfPath const &path) const
Return a pair of const_iterators [b, e), describing the maximal range such that for all i in the rang...
void swap(UsdStageLoadRules &l, UsdStageLoadRules &r)
Swap the contents of rules l and r.
bool empty() const
Return true if this table is empty.
iterator end()
Return an iterator denoting the end of the table.
bool erase(SdfPath const &path)
Remove the element with path path from the table as well as all elements whose paths are prefixed by ...
void ParallelForEach(Callback const &visitFn)
ParallelForEach: parallel iteration over all of the key-value pairs in the path table.
const_iterator begin() const
Return a const_iterator to the start of the table.
A path value used to locate objects in layers or scenegraphs.
iterator begin()
Return an iterator to the start of the table.
_IterBoolPair insert(value_type const &value)
Insert value into the table, and additionally insert default entries for all ancestral paths of value...
void clear()
Remove all elements from the table, leaving size() == 0.
SdfPathTable()
Default constructor.
std::vector< size_t > GetBucketSizes() const
Return a vector of the count of elements in each bucket.
static SDF_API const SdfPath & AbsoluteRootPath()
The absolute path representing the top of the namespace hierarchy.
void swap(SdfPathTable &other)
Swap this table's contents with other.
iterator find(SdfPath const &path)
Return an iterator to the element corresponding to path, or end() if there is none.
A mapping from SdfPath to MappedType, somewhat similar to map<SdfPath, MappedType> and TfHashMap<SdfP...
std::pair< iterator, iterator > FindSubtreeRange(SdfPath const &path)
Return a pair of iterators [b, e), describing the maximal range such that for all i in the range,...
void erase(iterator const &i)
Remove the element pointed to by i from the table as well as all elements whose paths are prefixed by...
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
void ClearInParallel()
Equivalent to clear(), but destroy contained objects in parallel.