52qsizetype qCalculateBlockSize(qsizetype elementCount, qsizetype elementSize, qsizetype headerSize)
noexcept
54 Q_ASSERT(elementSize);
57 if (Q_UNLIKELY(qMulOverflow(size_t(elementSize), size_t(elementCount), &bytes)) ||
58 Q_UNLIKELY(qAddOverflow(bytes, size_t(headerSize), &bytes)))
60 if (Q_UNLIKELY(qsizetype(bytes) < 0))
63 return qsizetype(bytes);
87 CalculateGrowingBlockSizeResult result = {
88 qsizetype(-1), qsizetype(-1)
91 qsizetype bytes = qCalculateBlockSize(elementCount, elementSize, headerSize);
95 size_t morebytes =
static_cast<size_t>(qNextPowerOfTwo(quint64(bytes)));
96 if (Q_UNLIKELY(qsizetype(morebytes) < 0)) {
100 bytes += (morebytes - bytes) / 2;
102 bytes = qsizetype(morebytes);
105 result.elementCount = (bytes - headerSize) / elementSize;
106 result.size = result.elementCount * elementSize + headerSize;
119calculateBlockSize(qsizetype capacity, qsizetype objectSize, qsizetype headerSize, QArrayData::AllocationOption option)
124 constexpr qsizetype FooterSize = qMax(
sizeof(QString::value_type),
sizeof(QByteArray::value_type));
125 if (objectSize <= FooterSize)
126 headerSize += FooterSize;
130 if (option == QArrayData::Grow) {
131 return qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
133 return { qCalculateBlockSize(capacity, objectSize, headerSize), capacity };
147 QArrayData::AllocationOption option)
noexcept
152 qsizetype headerSize =
sizeof(AlignedQArrayData);
153 const qsizetype headerAlignment =
alignof(AlignedQArrayData);
155 if (alignment > headerAlignment) {
160 headerSize += alignment - headerAlignment;
162 Q_ASSERT(headerSize > 0);
164 auto blockSize = calculateBlockSize(capacity, objectSize, headerSize, option);
165 capacity = blockSize.elementCount;
166 qsizetype allocSize = blockSize.size;
167 if (Q_UNLIKELY(allocSize < 0))
170 void *data =
nullptr;
171 QArrayData *header =
static_cast<QArrayData *>(::malloc(size_t(allocSize)));
172 if (Q_LIKELY(header)) {
173 header->ref_.storeRelaxed(1);
176 data = QTypedArrayData<
void>::dataStart(header, alignment);
177 header->alloc = capacity;
180 return { data, header };
184void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype alignment,
185 qsizetype capacity, AllocationOption option)
noexcept
189 Q_ASSERT(alignment >= qsizetype(
alignof(QArrayData))
190 && !(alignment & (alignment - 1)));
192 auto r = allocateHelper(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 QArrayData *header =
static_cast<QArrayData *>(::realloc(data, size_t(allocSize)));
237 header->alloc = capacity;
238 dataPointer =
reinterpret_cast<
char *>(header) + offset;
240 dataPointer =
nullptr;
242 return {header, dataPointer};