29 typedef typename std::conditional<pass_parameter_by_value, T,
const T &>::type parameter_type;
42 constexpr QArrayDataPointer(Data *header, T *adata, qsizetype n = 0)
noexcept
43#if QT_VERSION >= QT_VERSION_CHECK(7
, 0
, 0
) || defined(QT_BOOTSTRAPPED)
44 : ptr(adata), size(n), d(header)
46 : d(header), ptr(adata), size(n)
58 QArrayDataPointer(qsizetype alloc, qsizetype n = 0,
59 QArrayData::AllocationOption option = QArrayData::KeepSize)
60 : QArrayDataPointer(Data::allocate(alloc, option), n)
65 static QArrayDataPointer fromRawData(
const T *rawData, qsizetype length)
noexcept
67 Q_ASSERT(rawData || !length);
68 return {
nullptr,
const_cast<T *>(rawData), length };
151 template <
typename X> QArrayDataPointer<X> reinterpreted() &&
153 if (
sizeof(T) !=
sizeof(X)) {
154 Q_ASSERT(!d->isShared());
155 d->alloc = d->alloc *
sizeof(T) /
sizeof(X);
157 auto od =
reinterpret_cast<QTypedArrayData<X> *>(std::exchange(d,
nullptr));
158 auto optr =
reinterpret_cast<X *>(std::exchange(ptr,
nullptr));
159 return { od, optr, std::exchange(size, 0) };
185 void detachAndGrow(QArrayData::GrowthPosition where, qsizetype n,
const T **data,
186 QArrayDataPointer *old)
188 const bool detach = needsDetach();
189 bool readjusted =
false;
191 if (!n || (where == QArrayData::GrowsAtBeginning && freeSpaceAtBegin() >= n)
192 || (where == QArrayData::GrowsAtEnd && freeSpaceAtEnd() >= n))
194 readjusted = tryReadjustFreeSpace(where, n, data);
196 || (where == QArrayData::GrowsAtBeginning && freeSpaceAtBegin() >= n)
197 || (where == QArrayData::GrowsAtEnd && freeSpaceAtEnd() >= n));
201 reallocateAndGrow(where, n, old);
210 Q_NEVER_INLINE
void reallocateAndGrow(QArrayData::GrowthPosition where, qsizetype n,
211 QArrayDataPointer *old =
nullptr)
213 if constexpr (QTypeInfo<T>::isRelocatable &&
alignof(T) <=
alignof(std::max_align_t)) {
214 if (where == QArrayData::GrowsAtEnd && !old && !needsDetach() && n > 0) {
215 (*
this)->reallocate(constAllocatedCapacity() - freeSpaceAtEnd() + n, QArrayData::Grow);
220 QArrayDataPointer dp(allocateGrow(*
this, n, where));
222 Q_CHECK_PTR(dp.data());
223 if (where == QArrayData::GrowsAtBeginning) {
224 Q_ASSERT(dp.freeSpaceAtBegin() >= n);
226 Q_ASSERT(dp.freeSpaceAtEnd() >= n);
229 qsizetype toCopy = size;
232 if (needsDetach() || old)
233 dp->copyAppend(begin(), begin() + toCopy);
235 dp->moveAppend(begin(), begin() + toCopy);
236 Q_ASSERT(dp.size == toCopy);
261 bool tryReadjustFreeSpace(QArrayData::GrowthPosition pos, qsizetype n,
const T **data =
nullptr)
263 Q_ASSERT(!
this->needsDetach());
265 Q_ASSERT((pos == QArrayData::GrowsAtEnd &&
this->freeSpaceAtEnd() < n)
266 || (pos == QArrayData::GrowsAtBeginning &&
this->freeSpaceAtBegin() < n));
268 const qsizetype capacity =
this->constAllocatedCapacity();
269 const qsizetype freeAtBegin =
this->freeSpaceAtBegin();
270 const qsizetype freeAtEnd =
this->freeSpaceAtEnd();
272 qsizetype dataStartOffset = 0;
281 if (pos == QArrayData::GrowsAtEnd && freeAtBegin >= n
282 && ((3 *
this->size) < (2 * capacity))) {
284 }
else if (pos == QArrayData::GrowsAtBeginning && freeAtEnd >= n
285 && ((3 *
this->size) < capacity)) {
287 dataStartOffset = n + qMax(0, (capacity -
this->size - n) / 2);
293 relocate(dataStartOffset - freeAtBegin, data);
295 Q_ASSERT((pos == QArrayData::GrowsAtEnd &&
this->freeSpaceAtEnd() >= n)
296 || (pos == QArrayData::GrowsAtBeginning &&
this->freeSpaceAtBegin() >= n));
315 QArrayDataPointer sliced(qsizetype pos, qsizetype n)
const &
317 QArrayDataPointer result(n);
318 std::uninitialized_copy_n(begin() + pos, n, result.begin());
323 QArrayDataPointer sliced(qsizetype pos, qsizetype n) &&
326 return sliced(pos, n);
327 T *newBeginning = begin() + pos;
328 std::destroy(begin(), newBeginning);
329 std::destroy(newBeginning + n, end());
330 setBegin(newBeginning);
332 return std::move(*
this);
380 static QArrayDataPointer allocateGrow(
const QArrayDataPointer &from, qsizetype n, QArrayData::GrowthPosition position)
386 qsizetype minimalCapacity = qMax(from.size, from.constAllocatedCapacity()) + n;
389 minimalCapacity -= (position == QArrayData::GrowsAtEnd) ? from.freeSpaceAtEnd() : from.freeSpaceAtBegin();
390 qsizetype capacity = from.detachCapacity(minimalCapacity);
391 const bool grows = capacity > from.constAllocatedCapacity();
392 auto [header, dataPtr] = Data::allocate(capacity, grows ? QArrayData::Grow : QArrayData::KeepSize);
393 const bool valid = header !=
nullptr && dataPtr !=
nullptr;
395 return QArrayDataPointer(header, dataPtr);
399 dataPtr += (position == QArrayData::GrowsAtBeginning)
400 ? n + qMax(0, (header->alloc - from.size - n) / 2)
401 : from.freeSpaceAtBegin();
402 header->flags = from.flags();
403 return QArrayDataPointer(header, dataPtr);