54qsizetype qCalculateBlockSize(qsizetype elementCount, qsizetype elementSize, qsizetype headerSize)
noexcept
56 Q_ASSERT(elementSize);
59 if (Q_UNLIKELY(qMulOverflow(size_t(elementSize), size_t(elementCount), &bytes)) ||
60 Q_UNLIKELY(qAddOverflow(bytes, size_t(headerSize), &bytes)))
62 if (Q_UNLIKELY(qsizetype(bytes) < 0))
65 return qsizetype(bytes);
89 CalculateGrowingBlockSizeResult result = {
90 qsizetype(-1), qsizetype(-1)
93 qsizetype bytes = qCalculateBlockSize(elementCount, elementSize, headerSize);
97 size_t morebytes =
static_cast<size_t>(qNextPowerOfTwo(quint64(bytes)));
98 if (Q_UNLIKELY(qsizetype(morebytes) < 0)) {
102 bytes += (morebytes - bytes) / 2;
104 bytes = qsizetype(morebytes);
106 size_t fittedBytes = QtPrivate::expectedAllocSize(bytes,
alignof(std::max_align_t));
107 if (fittedBytes != 0)
110 result.elementCount = (bytes - headerSize) / elementSize;
111 result.size = result.elementCount * elementSize + headerSize;
143calculateBlockSize(qsizetype capacity, qsizetype objectSize, qsizetype headerSize, QArrayData::AllocationOption option)
148 constexpr qsizetype FooterSize = qMax(
sizeof(QString::value_type),
sizeof(QByteArray::value_type));
149 if (objectSize <= FooterSize)
150 headerSize += FooterSize;
154 if (option == QArrayData::Grow) {
155 return qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
157 return { qCalculateBlockSize(capacity, objectSize, headerSize), capacity };
162allocateHelper(QArrayData **dptr, qsizetype objectSize, qsizetype alignment, qsizetype capacity,
163 QArrayData::AllocationOption option)
noexcept
169 const qsizetype headerSize = calculateHeaderSize(alignment);
170 Q_ASSERT(headerSize > 0);
172 auto blockSize = calculateBlockSize(capacity, objectSize, headerSize, option);
173 capacity = blockSize.elementCount;
174 qsizetype allocSize = blockSize.size;
175 if (Q_UNLIKELY(allocSize < 0))
178 void *data =
nullptr;
179 void *mem = ::malloc(size_t(allocSize));
181 *dptr =
new (mem) QArrayData{1, {}, capacity};
183 data = QTypedArrayData<
void>::dataStart(*dptr, alignment);
190void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype alignment,
191 qsizetype capacity, AllocationOption option)
noexcept
195 Q_ASSERT(alignment >= qsizetype(
alignof(QArrayData))
196 && !(alignment & (alignment - 1)));
198 return allocateHelper(dptr, objectSize, alignment, capacity, option);
217QArrayData::reallocateUnaligned(QArrayData *data,
void *dataPointer,
218 qsizetype objectSize, qsizetype capacity, AllocationOption option)
noexcept
220 Q_ASSERT(!data || !data->isShared());
222 const qsizetype headerSize =
sizeof(AlignedQArrayData);
223 auto r = calculateBlockSize(capacity, objectSize, headerSize, option);
224 qsizetype allocSize = r.size;
225 capacity = r.elementCount;
226 if (Q_UNLIKELY(allocSize < 0))
229 const qptrdiff offset = dataPointer
230 ?
reinterpret_cast<
char *>(dataPointer) -
reinterpret_cast<
char *>(data)
232 Q_ASSERT(offset > 0);
233 Q_ASSERT(offset <= allocSize);
235 const bool hadData = data;
236 void *mem = ::realloc(data, size_t(allocSize));
237 QArrayData *header =
static_cast<QArrayData *>(mem);
240 header =
new (mem) QArrayData{0, {}, {}};
241 header->alloc = capacity;
242 dataPointer =
reinterpret_cast<
char *>(header) + offset;
244 dataPointer =
nullptr;
246 return {header, dataPointer};
249void QArrayData::deallocate(QArrayData *data, qsizetype objectSize,
250 qsizetype alignment)
noexcept
253 Q_ASSERT(alignment >= qsizetype(
alignof(QArrayData))
254 && !(alignment & (alignment - 1)));
256 const qsizetype capacity = data->alloc;
257 const qsizetype headerSize = calculateHeaderSize(alignment);
258 Q_ASSERT(headerSize > 0);
259 const auto blockSize = calculateBlockSize(capacity, objectSize,
260 headerSize, QArrayData::KeepSize);
261 const qsizetype allocSize = blockSize.size;
263 if (Q_LIKELY(allocSize > 0))
264 QtPrivate::sizedFree(data, size_t(allocSize));
static void * allocateHelper(QArrayData **dptr, qsizetype objectSize, qsizetype alignment, qsizetype capacity, QArrayData::AllocationOption option) noexcept