53qsizetype qCalculateBlockSize(qsizetype elementCount, qsizetype elementSize, qsizetype headerSize)
noexcept
55 Q_ASSERT(elementSize);
58 if (Q_UNLIKELY(qMulOverflow(size_t(elementSize), size_t(elementCount), &bytes)) ||
59 Q_UNLIKELY(qAddOverflow(bytes, size_t(headerSize), &bytes)))
61 if (Q_UNLIKELY(qsizetype(bytes) < 0))
64 return qsizetype(bytes);
88 CalculateGrowingBlockSizeResult result = {
89 qsizetype(-1), qsizetype(-1)
92 qsizetype bytes = qCalculateBlockSize(elementCount, elementSize, headerSize);
96 size_t morebytes =
static_cast<size_t>(qNextPowerOfTwo(quint64(bytes)));
97 if (Q_UNLIKELY(qsizetype(morebytes) < 0)) {
101 bytes += (morebytes - bytes) / 2;
103 bytes = qsizetype(morebytes);
105 size_t fittedBytes = QtPrivate::expectedAllocSize(bytes,
alignof(std::max_align_t));
106 if (fittedBytes != 0)
109 result.elementCount = (bytes - headerSize) / elementSize;
110 result.size = result.elementCount * elementSize + headerSize;
142calculateBlockSize(qsizetype capacity, qsizetype objectSize, qsizetype headerSize, QArrayData::AllocationOption option)
147 constexpr qsizetype FooterSize = qMax(
sizeof(QString::value_type),
sizeof(QByteArray::value_type));
148 if (objectSize <= FooterSize)
149 headerSize += FooterSize;
153 if (option == QArrayData::Grow) {
154 return qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
156 return { qCalculateBlockSize(capacity, objectSize, headerSize), capacity };
161allocateHelper(QArrayData **dptr, qsizetype objectSize, qsizetype alignment, qsizetype capacity,
162 QArrayData::AllocationOption option)
noexcept
168 const qsizetype headerSize = calculateHeaderSize(alignment);
169 Q_ASSERT(headerSize > 0);
171 auto blockSize = calculateBlockSize(capacity, objectSize, headerSize, option);
172 capacity = blockSize.elementCount;
173 qsizetype allocSize = blockSize.size;
174 if (Q_UNLIKELY(allocSize < 0))
177 void *data =
nullptr;
178 void *mem = ::malloc(size_t(allocSize));
180 *dptr =
new (mem) QArrayData{1, {}, capacity};
182 data = QTypedArrayData<
void>::dataStart(*dptr, alignment);
189void *QArrayData::allocate(QArrayData **dptr, qsizetype objectSize, qsizetype alignment,
190 qsizetype capacity, AllocationOption option)
noexcept
194 Q_ASSERT(alignment >= qsizetype(
alignof(QArrayData))
195 && !(alignment & (alignment - 1)));
197 return allocateHelper(dptr, objectSize, alignment, capacity, option);
216QArrayData::reallocateUnaligned(QArrayData *data,
void *dataPointer,
217 qsizetype objectSize, qsizetype capacity, AllocationOption option)
noexcept
219 Q_ASSERT(!data || !data->isShared());
221 const qsizetype headerSize =
sizeof(AlignedQArrayData);
222 auto r = calculateBlockSize(capacity, objectSize, headerSize, option);
223 qsizetype allocSize = r.size;
224 capacity = r.elementCount;
225 if (Q_UNLIKELY(allocSize < 0))
228 const qptrdiff offset = dataPointer
229 ?
reinterpret_cast<
char *>(dataPointer) -
reinterpret_cast<
char *>(data)
231 Q_ASSERT(offset > 0);
232 Q_ASSERT(offset <= allocSize);
234 const bool hadData = data;
235 void *mem = ::realloc(data, size_t(allocSize));
236 QArrayData *header =
static_cast<QArrayData *>(mem);
239 header =
new (mem) QArrayData{0, {}, {}};
240 header->alloc = capacity;
241 dataPointer =
reinterpret_cast<
char *>(header) + offset;
243 dataPointer =
nullptr;
245 return {header, dataPointer};
248void QArrayData::deallocate(QArrayData *data, qsizetype objectSize,
249 qsizetype alignment)
noexcept
252 Q_ASSERT(alignment >= qsizetype(
alignof(QArrayData))
253 && !(alignment & (alignment - 1)));
255 const qsizetype capacity = data->alloc;
256 const qsizetype headerSize = calculateHeaderSize(alignment);
257 Q_ASSERT(headerSize > 0);
258 const auto blockSize = calculateBlockSize(capacity, objectSize,
259 headerSize, QArrayData::KeepSize);
260 const qsizetype allocSize = blockSize.size;
262 if (Q_LIKELY(allocSize > 0))
263 QtPrivate::sizedFree(data, size_t(allocSize));
static void * allocateHelper(QArrayData **dptr, qsizetype objectSize, qsizetype alignment, qsizetype capacity, QArrayData::AllocationOption option) noexcept