24 #ifndef PXR_BASE_TF_SMALL_VECTOR_H 25 #define PXR_BASE_TF_SMALL_VECTOR_H 36 #include <initializer_list> 41 #include <type_traits> 43 PXR_NAMESPACE_OPEN_SCOPE
47 class TfSmallVectorBase
50 using size_type = std::uint32_t;
51 using difference_type = std::int32_t;
58 static constexpr size_type ComputeSerendipitousLocalCapacity() {
59 return (
alignof(U) <=
alignof(_Data<U, 0>))
60 ?
sizeof(_Data<U, 0>) /
sizeof(U)
67 template <
typename Iterator>
68 static Iterator _UninitializedMove(
69 Iterator first, Iterator last, Iterator dest) {
70 return std::uninitialized_copy(
71 std::make_move_iterator(first),
72 std::make_move_iterator(last),
79 static void _MoveConstruct(U *p, U *src) {
80 new (p) U(std::move(*src));
86 template <
typename U,
size_type M >
90 U *GetLocalStorage() {
91 return reinterpret_cast<U *>(_local);
94 const U *GetLocalStorage()
const {
95 return reinterpret_cast<const U *>(_local);
98 U *GetRemoteStorage() {
102 const U *GetRemoteStorage()
const {
106 void SetRemoteStorage(U *p) {
112 alignas(U)
char _local[
sizeof(U)*M];
120 template <
typename U >
124 U *GetLocalStorage() {
129 const U *GetLocalStorage()
const {
134 U *GetRemoteStorage() {
138 const U *GetRemoteStorage()
const {
142 void SetRemoteStorage(U *p) {
176 template <
typename T, u
int32_t N >
178 :
public TfSmallVectorBase
192 typedef T value_type;
193 typedef T& reference;
194 typedef const T& const_reference;
202 using const_iterator =
const T*;
203 typedef std::reverse_iterator<iterator> reverse_iterator;
204 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
217 value_type *d =
data();
218 for (size_type i = 0; i < n; ++i) {
219 new (d + i) value_type();
228 std::uninitialized_fill_n(
data(), n, v);
237 value_type *d =
data();
238 for (size_type i = 0; i < n; ++i) {
239 new (d + i) value_type;
246 _InitStorage(rhs.
size());
247 std::uninitialized_copy(rhs.begin(), rhs.end(), begin());
255 if (rhs.size() > N) {
256 _data.SetRemoteStorage(rhs._data.GetRemoteStorage());
265 _UninitializedMove(rhs.begin(), rhs.end(), begin());
276 template<
typename _ForwardIterator>
277 using _EnableIfForwardIterator =
278 typename std::enable_if<
280 typename std::iterator_traits<
281 _ForwardIterator>::iterator_category,
282 std::forward_iterator_tag
288 template<
typename ForwardIterator,
289 typename = _EnableIfForwardIterator<ForwardIterator>>
292 _InitStorage(std::distance(first, last));
293 std::uninitialized_copy(first, last, begin());
307 assign(rhs.begin(), rhs.end());
324 assign(ilist.begin(), ilist.end());
332 if (_IsLocal() && rhs._IsLocal()) {
337 std::swap_ranges(smaller->begin(), smaller->end(), larger->begin());
341 for (size_type i = smaller->
size(); i < larger->
size(); ++i) {
342 _MoveConstruct(smaller->
data() + i, &(*larger)[i]);
343 (*larger)[i].~value_type();
347 std::swap(smaller->_size, larger->_size);
352 else if (!_IsLocal() && !rhs._IsLocal()) {
353 value_type *tmp = _data.GetRemoteStorage();
354 _data.SetRemoteStorage(rhs._data.GetRemoteStorage());
355 rhs._data.SetRemoteStorage(tmp);
369 value_type *remoteStorage = remote->_GetStorage();
377 for (size_type i = 0; i < local->
size(); ++i) {
379 remote->_data.GetLocalStorage() + i, &(*local)[i]);
380 (*local)[i].~value_type();
385 local->_data.SetRemoteStorage(remoteStorage);
389 std::swap(remote->_capacity, local->_capacity);
396 iterator
insert(const_iterator it, value_type &&v) {
397 return _Insert(it, std::move(v));
402 iterator
insert(const_iterator it,
const value_type &v) {
403 return _Insert(it, v);
409 return erase(it, it + 1);
414 iterator
erase(const_iterator it, const_iterator last) {
415 value_type *p = const_cast<value_type *>(&*it);
416 value_type *q = const_cast<value_type *>(&*last);
423 const size_type num = std::distance(p, q);
430 for (value_type *i = (e - num); i != e; ++i) {
448 _GrowStorage(newCapacity);
454 void resize(size_type newSize,
const value_type &v = value_type()) {
457 if (newSize <
size()) {
464 else if (newSize >
size()) {
466 std::uninitialized_fill(
data() +
size(),
data() + newSize, v);
482 template<
typename ForwardIterator,
483 typename = _EnableIfForwardIterator<ForwardIterator>>
484 void assign(ForwardIterator first, ForwardIterator last) {
486 const size_type newSize = std::distance(first, last);
488 std::uninitialized_copy(first, last, begin());
494 void assign(std::initializer_list<T> ilist) {
495 assign(ilist.begin(), ilist.end());
500 template <
typename... Args >
503 _GrowStorage(_NextCapacity());
505 new (
data() +
size()) value_type(std::forward<Args>(args)...);
524 template <
typename ForwardIterator>
525 void insert(iterator pos, ForwardIterator first, ForwardIterator last)
529 typename std::iterator_traits<ForwardIterator>::iterator_category,
530 std::forward_iterator_tag>::value,
531 "Input Iterators not supported.");
536 const bool insertAtEnd = pos == end();
538 const long numNewElems = std::distance(first, last);
539 const size_type neededCapacity =
size() + numNewElems;
540 const size_type nextCapacity =
541 std::max(_NextCapacity(), neededCapacity);
553 _GrowStorage(nextCapacity);
555 std::uninitialized_copy(first, last, end());
556 _size += numNewElems;
565 const size_type posI = std::distance(begin(), pos);
566 value_type *newStorage = _Allocate(nextCapacity);
568 iterator newPrefixBegin = iterator(newStorage);
569 iterator newPos = newPrefixBegin + posI;
570 iterator newSuffixBegin = newPos + numNewElems;
571 _UninitializedMove(begin(), pos, newPrefixBegin);
572 std::uninitialized_copy(first, last, newPos);
573 _UninitializedMove(pos, end(), newSuffixBegin);
578 _data.SetRemoteStorage(newStorage);
579 _capacity = nextCapacity;
592 const long numMoveElems = std::distance(pos, end());
593 const long numUninitMoves = std::min(numNewElems, numMoveElems);
594 const long numInitMoves = numMoveElems - numUninitMoves;
595 const long numUninitNews = numNewElems - numUninitMoves;
596 const long numInitNews = numNewElems - numUninitNews;
599 iterator umSrc = pos + numInitMoves;
600 iterator umDst = end() + numUninitNews;
601 _UninitializedMove(umSrc, end(), umDst);
602 std::copy_backward(pos, umSrc, umDst);
605 for (
long i=0; i<numInitNews; ++i, ++first, ++pos) {
608 std::uninitialized_copy(first, last, end());
611 _size += numNewElems;
616 void insert(iterator pos, std::initializer_list<T> ilist) {
617 insert(pos, ilist.begin(), ilist.end());
623 back().~value_type();
636 return std::numeric_limits<size_type>::max();
666 return iterator(_GetStorage());
669 const_iterator begin()
const {
670 return const_iterator(_GetStorage());
673 const_iterator cbegin()
const {
683 return iterator(_GetStorage() +
size());
686 const_iterator end()
const {
687 return const_iterator(_GetStorage() +
size());
690 const_iterator cend()
const {
699 reverse_iterator rbegin() {
700 return reverse_iterator(end());
703 const_reverse_iterator rbegin()
const {
704 return const_reverse_iterator(end());
707 const_reverse_iterator crbegin()
const {
716 reverse_iterator rend() {
717 return reverse_iterator(begin());
720 const_reverse_iterator rend()
const {
721 return const_reverse_iterator(begin());
724 const_reverse_iterator crend()
const {
757 return *(
data() + i);
763 return *(
data() + i);
769 return _GetStorage();
774 const value_type *
data()
const {
775 return _GetStorage();
781 return size() == rhs.
size() && std::equal(begin(), end(), rhs.begin());
793 bool _IsLocal()
const {
794 return _capacity <= N;
799 value_type *_GetStorage() {
800 return _IsLocal() ? _data.GetLocalStorage() : _data.GetRemoteStorage();
805 const value_type *_GetStorage()
const {
806 return _IsLocal() ? _data.GetLocalStorage() : _data.GetRemoteStorage();
810 void _FreeStorage() {
812 free(_data.GetRemoteStorage());
818 value_type *b =
data();
819 value_type *e = b +
size();
820 for (value_type *p = b; p != e; ++p) {
826 static value_type *_Allocate(size_type
size) {
827 return static_cast<value_type *>(malloc(
sizeof(value_type) *
size));
831 void _InitStorage(size_type
size) {
833 _data.SetRemoteStorage(_Allocate(
size));
841 void _GrowStorage(
const size_type newCapacity) {
842 value_type *newStorage = _Allocate(newCapacity);
843 _UninitializedMove(begin(), end(), iterator(newStorage));
846 _data.SetRemoteStorage(newStorage);
847 _capacity = newCapacity;
853 size_type _NextCapacity()
const {
855 return cap + (cap / 2) + 1;
864 template <
typename U >
865 iterator _Insert(const_iterator it, U &&v) {
866 value_type *newEntry;
878 const size_type newCapacity = _NextCapacity();
879 value_type *newStorage = _Allocate(newCapacity);
881 value_type *i = const_cast<value_type *>(&*it);
882 value_type *curData =
data();
883 newEntry = _UninitializedMove(curData, i, newStorage);
885 new (newEntry) value_type(std::forward<U>(v));
887 _UninitializedMove(i, curData +
size(), newEntry + 1);
892 _data.SetRemoteStorage(newStorage);
893 _capacity = newCapacity;
900 newEntry = const_cast<value_type *>(&*it);
901 value_type *last = const_cast<value_type *>(&
back());
902 new (
data() +
size()) value_type(std::move(*last));
903 std::move_backward(newEntry, last, last + 1);
906 newEntry->~value_type();
907 new (newEntry) value_type(std::forward<U>(v));
912 return iterator(newEntry);
917 _Data<value_type, N> _data;
929 template <
typename T, u
int32_t N >
937 PXR_NAMESPACE_CLOSE_SCOPE
void swap(ArAssetInfo &lhs, ArAssetInfo &rhs)
void push_back(value_type &&v)
Move an entry to the back of the vector.
TfSmallVector(size_type n)
Construct a vector holding n value-initialized elements.
void reserve(size_type newCapacity)
Reserve storage for newCapacity entries.
reference operator[](size_type i)
Access the specified element.
static constexpr size_type max_size()
Returns the maximum size of this vector.
This is a small-vector class with local storage optimization, the local storage can be specified via ...
bool empty() const
Returns true if this vector is empty.
const_reference back() const
Returns the last elements in the vector.
value_type * data()
Direct access to the underlying array.
void swap(TfSmallVector &rhs)
Swap two vector instances.
void insert(iterator pos, ForwardIterator first, ForwardIterator last)
Copy the range denoted by [first, last) into this vector before pos.
size_type capacity() const
Returns the current capacity of this vector.
const value_type * data() const
Direct access to the underlying array.
reference back()
Returns the last element in the vector.
void assign(ForwardIterator first, ForwardIterator last)
Clears any previously held entries, and copies entries between [ first, last ) to this vector.
void assign(std::initializer_list< T > ilist)
Replace existing contents with the contents of ilist.
iterator erase(const_iterator it)
Erase an entry at the given iterator.
TfSmallVector & operator=(std::initializer_list< T > ilist)
Replace existing contents with the contents of ilist.
void resize(size_type newSize, const value_type &v=value_type())
Resize the vector to newSize and insert copies of \v.
void insert(iterator pos, std::initializer_list< T > ilist)
Insert elements from ilist starting at position pos.
bool operator==(const TfSmallVector &rhs) const
Lexicographically compares the elements in the vectors for equality.
void swap(UsdStageLoadRules &l, UsdStageLoadRules &r)
Swap the contents of rules l and r.
const_reference front() const
Returns the first element in the vector.
void pop_back()
Remove the entry at the back of the vector.
~TfSmallVector()
Destructor.
TfSmallVector(const TfSmallVector &rhs)
Copy constructor.
void clear()
Clear the entries in the vector.
TfSmallVector & operator=(TfSmallVector &&rhs)
Move assignment operator.
void push_back(const value_type &v)
Copy an entry to the back of the vector,.
iterator insert(const_iterator it, const value_type &v)
Insert an entry at the given iterator.
static constexpr size_type internal_capacity()
Returns the local storage capacity.
TfSmallVector(ForwardIterator first, ForwardIterator last)
Creates a new vector containing copies of the data between first and last.
size_type size() const
Returns the current size of the vector.
iterator erase(const_iterator it, const_iterator last)
Erase entries between [ first, last ) from the vector.
void emplace_back(Args &&... args)
Emplace an entry at the back of the vector.
TfSmallVector & operator=(const TfSmallVector &rhs)
Assignment operator.
DefaultInitTag
Construct a vector holding n default-initialized elements.
TfSmallVector(std::initializer_list< T > values)
Construct a new vector from initializer list.
TfSmallVector(TfSmallVector &&rhs)
Move constructor.
TfSmallVector(size_type n, const value_type &v)
Construct a vector holding n copies of v.
bool operator!=(const TfSmallVector &rhs) const
Lexicographically compares the elements in the vectors for inequality.
const_reference operator[](size_type i) const
Access the specified element.
reference front()
Returns the first element in the vector.
iterator insert(const_iterator it, value_type &&v)
Insert an rvalue-reference entry at the given iterator position.