31 typedef typename std::conditional<pass_parameter_by_value, T,
const T &>::type parameter_type;
45 constexpr QArrayDataPointer(Data *header, T *adata, qsizetype n = 0)
noexcept
46#if QT_VERSION >= QT_VERSION_CHECK(7
, 0
, 0
) || defined(QT_BOOTSTRAPPED)
47 : ptr(adata), size(n), d(header)
49 : d(header), ptr(adata), size(n)
61 QArrayDataPointer(qsizetype alloc, qsizetype n = 0,
62 QArrayData::AllocationOption option = QArrayData::KeepSize)
63 : QArrayDataPointer(Data::allocate(alloc, option), n)
68 static QArrayDataPointer fromRawData(
const T *rawData, qsizetype length)
noexcept
70 Q_ASSERT(rawData || !length);
71 return {
nullptr,
const_cast<T *>(rawData), length };
167 template <
typename X> QArrayDataPointer<X> reinterpreted() &&
169 if (
sizeof(T) !=
sizeof(X)) {
170 Q_ASSERT(!d->isShared());
171 d->alloc = d->alloc *
sizeof(T) /
sizeof(X);
173 auto od =
reinterpret_cast<QTypedArrayData<X> *>(std::exchange(d,
nullptr));
174 auto optr =
reinterpret_cast<X *>(std::exchange(ptr,
nullptr));
175 return { od, optr, std::exchange(size, 0) };
201 void detachAndGrow(QArrayData::GrowthPosition where, qsizetype n,
const T **data,
202 QArrayDataPointer *old)
204 const bool detach = needsDetach();
205 bool readjusted =
false;
207 if (!n || (where == QArrayData::GrowsAtBeginning && freeSpaceAtBegin() >= n)
208 || (where == QArrayData::GrowsAtEnd && freeSpaceAtEnd() >= n))
210 readjusted = tryReadjustFreeSpace(where, n, data);
212 || (where == QArrayData::GrowsAtBeginning && freeSpaceAtBegin() >= n)
213 || (where == QArrayData::GrowsAtEnd && freeSpaceAtEnd() >= n));
217 reallocateAndGrow(where, n, old);
226 Q_NEVER_INLINE
void reallocateAndGrow(QArrayData::GrowthPosition where, qsizetype n,
227 QArrayDataPointer *old =
nullptr)
229 if constexpr (QTypeInfo<T>::isRelocatable &&
alignof(T) <=
alignof(std::max_align_t)) {
230 if (where == QArrayData::GrowsAtEnd && !old && !needsDetach() && n > 0) {
231 (*
this)->reallocate(constAllocatedCapacity() - freeSpaceAtEnd() + n, QArrayData::Grow);
236 QArrayDataPointer dp(allocateGrow(*
this, n, where));
238 Q_CHECK_PTR(dp.data());
239 if (where == QArrayData::GrowsAtBeginning) {
240 Q_ASSERT(dp.freeSpaceAtBegin() >= n);
242 Q_ASSERT(dp.freeSpaceAtEnd() >= n);
245 qsizetype toCopy = size;
248 if (needsDetach() || old)
249 dp->copyAppend(begin(), begin() + toCopy);
251 dp->moveAppend(begin(), begin() + toCopy);
252 Q_ASSERT(dp.size == toCopy);
277 bool tryReadjustFreeSpace(QArrayData::GrowthPosition pos, qsizetype n,
const T **data =
nullptr)
279 Q_ASSERT(!
this->needsDetach());
281 Q_ASSERT((pos == QArrayData::GrowsAtEnd &&
this->freeSpaceAtEnd() < n)
282 || (pos == QArrayData::GrowsAtBeginning &&
this->freeSpaceAtBegin() < n));
284 const qsizetype capacity =
this->constAllocatedCapacity();
285 const qsizetype freeAtBegin =
this->freeSpaceAtBegin();
286 const qsizetype freeAtEnd =
this->freeSpaceAtEnd();
288 qsizetype dataStartOffset = 0;
297 if (pos == QArrayData::GrowsAtEnd && freeAtBegin >= n
298 && ((3 *
this->size) < (2 * capacity))) {
300 }
else if (pos == QArrayData::GrowsAtBeginning && freeAtEnd >= n
301 && ((3 *
this->size) < capacity)) {
303 dataStartOffset = n + qMax(0, (capacity -
this->size - n) / 2);
309 relocate(dataStartOffset - freeAtBegin, data);
311 Q_ASSERT((pos == QArrayData::GrowsAtEnd &&
this->freeSpaceAtEnd() >= n)
312 || (pos == QArrayData::GrowsAtBeginning &&
this->freeSpaceAtBegin() >= n));
331 QArrayDataPointer sliced(qsizetype pos, qsizetype n)
const &
333 QArrayDataPointer result(n);
334 std::uninitialized_copy_n(begin() + pos, n, result.begin());
339 QArrayDataPointer sliced(qsizetype pos, qsizetype n) &&
342 return sliced(pos, n);
343 T *newBeginning = begin() + pos;
344 std::destroy(begin(), newBeginning);
345 std::destroy(newBeginning + n, end());
346 setBegin(newBeginning);
348 return std::move(*
this);
401 static QArrayDataPointer allocateGrow(
const QArrayDataPointer &from, qsizetype n, QArrayData::GrowthPosition position)
407 qsizetype minimalCapacity = qMax(from.size, from.constAllocatedCapacity()) + n;
410 minimalCapacity -= (position == QArrayData::GrowsAtEnd) ? from.freeSpaceAtEnd() : from.freeSpaceAtBegin();
411 qsizetype capacity = from.detachCapacity(minimalCapacity);
412 const bool grows = capacity > from.constAllocatedCapacity();
413 auto [header, dataPtr] = Data::allocate(capacity, grows ? QArrayData::Grow : QArrayData::KeepSize);
414 const bool valid = header !=
nullptr && dataPtr !=
nullptr;
416 return QArrayDataPointer(header, dataPtr);
420 dataPtr += (position == QArrayData::GrowsAtBeginning)
421 ? n + qMax(0, (header->alloc - from.size - n) / 2)
422 : from.freeSpaceAtBegin();
423 header->flags = from.flags();
424 return QArrayDataPointer(header, dataPtr);