8#include <QtCore/qarraydata.h>
9#include <QtCore/qcontainertools_impl.h>
10#include <QtCore/qnamespace.h>
22template <
class T>
struct QArrayDataPointer;
30 static_assert (
std::is_nothrow_destructible_v<T>,
"Types with throwing destructors are not supported in Qt containers.");
43 Q_ASSERT(
this->isMutable() || b == e);
44 Q_ASSERT(!
this->isShared() || b == e);
46 Q_ASSERT((e - b) <=
this->freeSpaceAtEnd());
51 ::memcpy(
static_cast<
void *>(
this->end()),
static_cast<
const void *>(b), (e - b) *
sizeof(T));
52 this->size += (e - b);
57 Q_ASSERT(!
this->isShared() || n == 0);
58 Q_ASSERT(
this->freeSpaceAtEnd() >= n);
62 T *where =
this->end();
63 this->size += qsizetype(n);
75 Q_ASSERT(
this->isMutable());
76 Q_ASSERT(!
this->isShared());
77 Q_ASSERT(newSize < size_t(
this->size));
79 this->size = qsizetype(newSize);
85 Q_ASSERT(
this->d->ref_.loadRelaxed() == 0);
91 T *
createHole(QArrayData::GrowthPosition pos, qsizetype where, qsizetype n)
93 Q_ASSERT((pos == QArrayData::GrowsAtBeginning && n <=
this->freeSpaceAtBegin()) ||
94 (pos == QArrayData::GrowsAtEnd && n <=
this->freeSpaceAtEnd()));
96 T *insertionPoint =
this->ptr + where;
97 if (pos == QArrayData::GrowsAtEnd) {
98 if (where <
this->size)
99 ::memmove(
static_cast<
void *>(insertionPoint + n),
static_cast<
void *>(insertionPoint), (
this->size - where) *
sizeof(T));
101 Q_ASSERT(where == 0);
106 return insertionPoint;
109 void insert(qsizetype i,
const T *data, qsizetype n)
111 typename Data::GrowthPosition pos = Data::GrowsAtEnd;
112 if (
this->size != 0 && i == 0)
113 pos = Data::GrowsAtBeginning;
116 this->detachAndGrow(pos, n, &data, &oldData);
117 Q_ASSERT((pos == Data::GrowsAtBeginning &&
this->freeSpaceAtBegin() >= n) ||
118 (pos == Data::GrowsAtEnd &&
this->freeSpaceAtEnd() >= n));
120 T *where = createHole(pos, i, n);
121 ::memcpy(
static_cast<
void *>(where),
static_cast<
const void *>(data), n *
sizeof(T));
128 typename Data::GrowthPosition pos = Data::GrowsAtEnd;
129 if (
this->size != 0 && i == 0)
130 pos = Data::GrowsAtBeginning;
132 this->detachAndGrow(pos, n,
nullptr,
nullptr);
133 Q_ASSERT((pos == Data::GrowsAtBeginning &&
this->freeSpaceAtBegin() >= n) ||
134 (pos == Data::GrowsAtEnd &&
this->freeSpaceAtEnd() >= n));
136 T *where = createHole(pos, i, n);
141 template<
typename... Args>
144 bool detach =
this->needsDetach();
146 if (i ==
this->size &&
this->freeSpaceAtEnd()) {
147 new (
this->end()) T(
std::forward<Args>(args)...);
151 if (i == 0 &&
this->freeSpaceAtBegin()) {
152 new (
this->begin() - 1) T(
std::forward<Args>(args)...);
158 T tmp(
std::forward<Args>(args)...);
159 typename QArrayData::GrowthPosition pos = QArrayData::GrowsAtEnd;
160 if (
this->size != 0 && i == 0)
161 pos = QArrayData::GrowsAtBeginning;
163 this->detachAndGrow(pos, 1,
nullptr,
nullptr);
165 T *where = createHole(pos, i, 1);
166 new (where) T(
std::move(tmp));
172 Q_ASSERT(
this->isMutable());
174 Q_ASSERT(b >=
this->begin() && b <
this->end());
175 Q_ASSERT(e >
this->begin() && e <=
this->end());
181 if (b ==
this->begin() && e !=
this->end()) {
183 }
else if (e !=
this->end()) {
184 ::memmove(
static_cast<
void *>(b),
static_cast<
void *>(e),
185 (
static_cast<T *>(
this->end()) - e) *
sizeof(T));
192 Q_ASSERT(
this->isMutable());
193 Q_ASSERT(
this->size);
200 Q_ASSERT(
this->isMutable());
201 Q_ASSERT(
this->size);
205 template <
typename Predicate>
208 qsizetype result = 0;
212 if (!
this->needsDetach()) {
213 auto end =
this->end();
214 auto it = std::remove_if(
this->begin(), end, pred);
216 result =
std::distance(it, end);
220 const auto begin =
this->begin();
221 const auto end =
this->end();
222 auto it = std::find_if(begin, end, pred);
227 Q_CHECK_PTR(other.data());
228 auto dest = other.begin();
230 dest =
std::uninitialized_copy(begin, it, dest);
231 dest = q_uninitialized_remove_copy_if(
std::next(it), end, dest, pred);
232 other.size =
std::distance(other.data(), dest);
233 result =
this->size - other.size;
243 auto it =
this->begin();
244 std::for_each(ranges.begin(), ranges.end(), [&it](
const auto &span) {
245 it = std::copy(span.begin, span.end, it);
247 this->size =
std::distance(
this->begin(), it);
253 Q_ASSERT(b >=
this->begin() && e <=
this->end());
256 ::memcpy(
static_cast<
void *>(b++),
static_cast<
const void *>(&t),
sizeof(T));
259 void reallocate(qsizetype alloc, QArrayData::AllocationOption option)
261 auto pair = Data::reallocateUnaligned(
this->d,
this->ptr, alloc, option);
262 Q_CHECK_PTR(pair.second);
263 Q_ASSERT(pair.first !=
nullptr);
264 this->d = pair.first;
265 this->ptr = pair.second;
273 static_assert (
std::is_nothrow_destructible_v<T>,
"Types with throwing destructors are not supported in Qt containers.");
284 Q_ASSERT(
this->isMutable() || b == e);
285 Q_ASSERT(!
this->isShared() || b == e);
287 Q_ASSERT((e - b) <=
this->freeSpaceAtEnd());
292 T *data =
this->begin();
294 new (data +
this->size) T(*b);
302 Q_ASSERT(!
this->isShared() || n == 0);
303 Q_ASSERT(
this->freeSpaceAtEnd() >= n);
307 T *data =
this->begin();
309 new (data +
this->size) T(t);
316 Q_ASSERT(
this->isMutable() || b == e);
317 Q_ASSERT(!
this->isShared() || b == e);
319 Q_ASSERT((e - b) <=
this->freeSpaceAtEnd());
324 T *data =
this->begin();
326 new (data +
this->size) T(
std::move(*b));
334 Q_ASSERT(
this->isMutable());
335 Q_ASSERT(!
this->isShared());
336 Q_ASSERT(newSize < size_t(
this->size));
338 std::destroy(
this->begin() + newSize,
this->end());
339 this->size = newSize;
348 Q_ASSERT(
this->d->ref_.loadRelaxed() == 0);
350 std::destroy(
this->begin(),
this->end());
480 void insert(qsizetype i,
const T *data, qsizetype n)
482 const bool growsAtBegin =
this->size != 0 && i == 0;
483 const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
486 this->detachAndGrow(pos, n, &data, &oldData);
487 Q_ASSERT((pos == Data::GrowsAtBeginning &&
this->freeSpaceAtBegin() >= n) ||
488 (pos == Data::GrowsAtEnd &&
this->freeSpaceAtEnd() >= n));
492 Q_ASSERT(
this->freeSpaceAtBegin() >= n);
495 new (
this->begin() - 1) T(data[n]);
508 const bool growsAtBegin =
this->size != 0 && i == 0;
509 const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
511 this->detachAndGrow(pos, n,
nullptr,
nullptr);
512 Q_ASSERT((pos == Data::GrowsAtBeginning &&
this->freeSpaceAtBegin() >= n) ||
513 (pos == Data::GrowsAtEnd &&
this->freeSpaceAtEnd() >= n));
517 Q_ASSERT(
this->freeSpaceAtBegin() >= n);
519 new (
this->begin() - 1) T(copy);
528 template<
typename... Args>
531 bool detach =
this->needsDetach();
533 if (i ==
this->size &&
this->freeSpaceAtEnd()) {
534 new (
this->end()) T(
std::forward<Args>(args)...);
538 if (i == 0 &&
this->freeSpaceAtBegin()) {
539 new (
this->begin() - 1) T(
std::forward<Args>(args)...);
545 T tmp(
std::forward<Args>(args)...);
546 const bool growsAtBegin =
this->size != 0 && i == 0;
547 const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
549 this->detachAndGrow(pos, 1,
nullptr,
nullptr);
552 Q_ASSERT(
this->freeSpaceAtBegin());
553 new (
this->begin() - 1) T(
std::move(tmp));
564 Q_ASSERT(
this->isMutable());
566 Q_ASSERT(b >=
this->begin() && b <
this->end());
567 Q_ASSERT(e >
this->begin() && e <=
this->end());
573 if (b ==
this->begin() && e !=
this->end()) {
576 const T *
const end =
this->end();
592 Q_ASSERT(
this->isMutable());
593 Q_ASSERT(
this->size);
601 Q_ASSERT(
this->isMutable());
602 Q_ASSERT(
this->size);
603 (
this->end() - 1)->~T();
611 Q_ASSERT(b >=
this->begin() && e <=
this->end());
622 static_assert (
std::is_nothrow_destructible_v<T>,
"Types with throwing destructors are not supported in Qt containers.");
701 void insert(qsizetype i,
const T *data, qsizetype n)
703 const bool growsAtBegin =
this->size != 0 && i == 0;
704 const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
707 this->detachAndGrow(pos, n, &data, &oldData);
708 Q_ASSERT((pos == Data::GrowsAtBeginning &&
this->freeSpaceAtBegin() >= n) ||
709 (pos == Data::GrowsAtEnd &&
this->freeSpaceAtEnd() >= n));
713 Q_ASSERT(
this->freeSpaceAtBegin() >= n);
716 new (
this->begin() - 1) T(data[n]);
729 const bool growsAtBegin =
this->size != 0 && i == 0;
730 const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
732 this->detachAndGrow(pos, n,
nullptr,
nullptr);
733 Q_ASSERT((pos == Data::GrowsAtBeginning &&
this->freeSpaceAtBegin() >= n) ||
734 (pos == Data::GrowsAtEnd &&
this->freeSpaceAtEnd() >= n));
738 Q_ASSERT(
this->freeSpaceAtBegin() >= n);
740 new (
this->begin() - 1) T(copy);
749 template<
typename... Args>
752 bool detach =
this->needsDetach();
754 if (i ==
this->size &&
this->freeSpaceAtEnd()) {
755 new (
this->end()) T(
std::forward<Args>(args)...);
759 if (i == 0 &&
this->freeSpaceAtBegin()) {
760 new (
this->begin() - 1) T(
std::forward<Args>(args)...);
766 T tmp(
std::forward<Args>(args)...);
767 const bool growsAtBegin =
this->size != 0 && i == 0;
768 const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
770 this->detachAndGrow(pos, 1,
nullptr,
nullptr);
772 Q_ASSERT(
this->freeSpaceAtBegin());
773 new (
this->begin() - 1) T(
std::move(tmp));
785 Q_ASSERT(
this->isMutable());
787 Q_ASSERT(b >=
this->begin() && b <
this->end());
788 Q_ASSERT(e >
this->begin() && e <=
this->end());
796 if (b ==
this->begin() && e !=
this->end()) {
798 }
else if (e !=
this->end()) {
799 memmove(
static_cast<
void *>(b),
static_cast<
const void *>(e), (
static_cast<
const T *>(
this->end()) - e)*
sizeof(T));
804 void reallocate(qsizetype alloc, QArrayData::AllocationOption option)
806 auto pair = Data::reallocateUnaligned(
this->d,
this->ptr, alloc, option);
807 Q_CHECK_PTR(pair.second);
808 Q_ASSERT(pair.first !=
nullptr);
809 this->d = pair.first;
810 this->ptr = pair.second;
814template <
class T,
class =
void>
854 template<
typename It>
857 Q_ASSERT(
this->isMutable() || b == e);
858 Q_ASSERT(!
this->isShared() || b == e);
859 const qsizetype distance =
std::distance(b, e);
860 Q_ASSERT(distance >= 0 && distance <=
this->allocatedCapacity() -
this->size);
863#if __cplusplus
>= 202002L
&& defined(__cpp_concepts) && defined(__cpp_lib_concepts)
864 constexpr bool canUseCopyAppend =
865 std::contiguous_iterator<It> &&
867 std::remove_cv_t<
typename std::iterator_traits<It>::value_type>,
870 if constexpr (canUseCopyAppend) {
871 this->copyAppend(std::to_address(b), std::to_address(e));
875 T *iter =
this->end();
876 for (; b != e; ++iter, ++b) {
889 const qsizetype n = e - b;
893 if (QtPrivate::q_points_into_range(b, *
this))
894 this->detachAndGrow(QArrayData::GrowsAtEnd, n, &b, &old);
896 this->detachAndGrow(QArrayData::GrowsAtEnd, n,
nullptr,
nullptr);
897 Q_ASSERT(
this->freeSpaceAtEnd() >= n);
899 this->copyAppend(b, b + n);
904 Q_ASSERT(
this->isMutable());
905 Q_ASSERT(!
this->isShared());
906 Q_ASSERT(newSize >
this->size);
907 Q_ASSERT(newSize -
this->size <=
this->freeSpaceAtEnd());
910 T *
const b =
this->begin() +
this->size;
911 T *
const e =
this->begin() + newSize;
912 if constexpr (std::is_constructible_v<T, Qt::Initialization>)
913 std::uninitialized_fill(b, e, Qt::Uninitialized);
915 std::uninitialized_default_construct(b, e);
916 this->size = newSize;
QGenericArrayOps< T > Type
void appendUninitialized(qsizetype newSize)
void appendIteratorRange(It b, It e, QtPrivate::IfIsForwardIterator< It >=true)
void growAppend(const T *b, const T *e)
qsizetype sourceCopyConstruct
QArrayDataPointer< T > * data
qsizetype sourceCopyAssign
void truncate(size_t newSize)
void insert(qsizetype i, qsizetype n, parameter_type t)
QArrayDataPointer< T >::parameter_type parameter_type
void moveAppend(T *b, T *e)
QTypedArrayData< T > Data
void emplace(qsizetype i, Args &&... args)
void copyAppend(const T *b, const T *e)
void eraseFirst() noexcept
void eraseLast() noexcept
void assign(T *b, T *e, parameter_type t)
void erase(T *b, qsizetype n)
void insert(qsizetype i, const T *data, qsizetype n)
void copyAppend(qsizetype n, parameter_type t)
QArrayDataPointer< T > * data
QTypedArrayData< T > Data
void reallocate(qsizetype alloc, QArrayData::AllocationOption option)
void insert(qsizetype i, const T *data, qsizetype n)
void emplace(qsizetype i, Args &&... args)
QGenericArrayOps< T >::parameter_type parameter_type
void erase(T *b, qsizetype n)
void insert(qsizetype i, qsizetype n, parameter_type t)
void moveAppend(T *b, T *e) noexcept
void eraseFirst() noexcept
QArrayDataPointer< T >::parameter_type parameter_type
void copyRanges(std::initializer_list< Span > ranges)
void erase(T *b, qsizetype n)
void eraseLast() noexcept
T * createHole(QArrayData::GrowthPosition pos, qsizetype where, qsizetype n)
void insert(qsizetype i, const T *data, qsizetype n)
void truncate(size_t newSize) noexcept
void emplace(qsizetype i, Args &&... args)
qsizetype eraseIf(Predicate pred)
void assign(T *b, T *e, parameter_type t) noexcept
void copyAppend(const T *b, const T *e) noexcept
void copyAppend(qsizetype n, parameter_type t) noexcept
void reallocate(qsizetype alloc, QArrayData::AllocationOption option)
void insert(qsizetype i, qsizetype n, parameter_type t)
QTypedArrayData< T > Data
void destroyAll() noexcept