QArrayDataPointer: add an allocating constructor

It's by far the most common use, so having to call two things is just
cumbersome.

Change-Id: I79e700614d034281bf55fffd178f454c4e31929e
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Thiago Macieira 2023-08-22 15:40:42 -07:00
parent 793cfec941
commit 2fd0996324
7 changed files with 41 additions and 40 deletions

View File

@ -685,7 +685,7 @@ QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel)
if (nbytes < SingleAllocLimit) {
// use maximum size
capacity += compressBound(uLong(nbytes)); // cannot overflow (both times)!
return QArrayDataPointer{QTypedArrayData<char>::allocate(capacity)};
return QArrayDataPointer<char>(capacity);
}
// for larger buffers, assume it compresses optimally, and
@ -695,7 +695,7 @@ QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel)
// but use a nearby power-of-two (faster)
capacity += std::max(qsizetype(compressBound(uLong(SingleAllocLimit))),
nbytes / MaxCompressionFactor);
return QArrayDataPointer{QTypedArrayData<char>::allocate(capacity, QArrayData::Grow)};
return QArrayDataPointer<char>(capacity, 0, QArrayData::Grow);
}();
if (out.data() == nullptr) // allocation failed
@ -783,7 +783,7 @@ QByteArray qUncompress(const uchar* data, qsizetype nbytes)
qsizetype capacity = std::max(qsizetype(expectedSize), // cannot overflow!
nbytes);
QArrayDataPointer d(QTypedArrayData<char>::allocate(capacity, QArrayData::KeepSize));
QArrayDataPointer<char> d(capacity);
return xxflate(ZLibOp::Decompression, std::move(d), {data + HeaderSize, nbytes - HeaderSize},
[] (z_stream *zs) { return inflateInit(zs); },
[] (z_stream *zs, size_t) { return inflate(zs, Z_NO_FLUSH); },
@ -1793,7 +1793,7 @@ QByteArray::QByteArray(const char *data, qsizetype size)
if (!size) {
d = DataPointer::fromRawData(&_empty, 0);
} else {
d = DataPointer(Data::allocate(size), size);
d = DataPointer(size, size);
Q_CHECK_PTR(d.data());
memcpy(d.data(), data, size);
d.data()[size] = '\0';
@ -1812,7 +1812,7 @@ QByteArray::QByteArray(qsizetype size, char ch)
if (size <= 0) {
d = DataPointer::fromRawData(&_empty, 0);
} else {
d = DataPointer(Data::allocate(size), size);
d = DataPointer(size, size);
Q_CHECK_PTR(d.data());
memset(d.data(), ch, size);
d.data()[size] = '\0';
@ -1828,7 +1828,7 @@ QByteArray::QByteArray(qsizetype size, Qt::Initialization)
if (size <= 0) {
d = DataPointer::fromRawData(&_empty, 0);
} else {
d = DataPointer(Data::allocate(size), size);
d = DataPointer(size, size);
Q_CHECK_PTR(d.data());
d.data()[size] = '\0';
}
@ -1917,7 +1917,7 @@ void QByteArray::reallocData(qsizetype alloc, QArrayData::AllocationOption optio
const bool cannotUseReallocate = d.freeSpaceAtBegin() > 0;
if (d->needsDetach() || cannotUseReallocate) {
DataPointer dd(Data::allocate(alloc, option), qMin(alloc, d.size));
DataPointer dd(alloc, qMin(alloc, d.size), option);
Q_CHECK_PTR(dd.data());
if (dd.size > 0)
::memcpy(dd.data(), d.data(), dd.size);

View File

@ -2492,7 +2492,7 @@ QString::QString(const QChar *unicode, qsizetype size)
if (!size) {
d = DataPointer::fromRawData(&_empty, 0);
} else {
d = DataPointer(Data::allocate(size), size);
d = DataPointer(size, size);
Q_CHECK_PTR(d.data());
memcpy(d.data(), unicode, size * sizeof(QChar));
d.data()[size] = '\0';
@ -2511,7 +2511,7 @@ QString::QString(qsizetype size, QChar ch)
if (size <= 0) {
d = DataPointer::fromRawData(&_empty, 0);
} else {
d = DataPointer(Data::allocate(size), size);
d = DataPointer(size, size);
Q_CHECK_PTR(d.data());
d.data()[size] = '\0';
char16_t *b = d.data();
@ -2532,7 +2532,7 @@ QString::QString(qsizetype size, Qt::Initialization)
if (size <= 0) {
d = DataPointer::fromRawData(&_empty, 0);
} else {
d = DataPointer(Data::allocate(size), size);
d = DataPointer(size, size);
Q_CHECK_PTR(d.data());
d.data()[size] = '\0';
}
@ -2550,7 +2550,7 @@ QString::QString(qsizetype size, Qt::Initialization)
*/
QString::QString(QChar ch)
{
d = DataPointer(Data::allocate(1), 1);
d = DataPointer(1, 1);
Q_CHECK_PTR(d.data());
d.data()[0] = ch.unicode();
d.data()[1] = '\0';
@ -2768,7 +2768,7 @@ void QString::reallocData(qsizetype alloc, QArrayData::AllocationOption option)
const bool cannotUseReallocate = d.freeSpaceAtBegin() > 0;
if (d->needsDetach() || cannotUseReallocate) {
DataPointer dd(Data::allocate(alloc, option), qMin(alloc, d.size));
DataPointer dd(alloc, qMin(alloc, d.size), option);
Q_CHECK_PTR(dd.data());
if (dd.size > 0)
::memcpy(dd.data(), d.data(), dd.size * sizeof(QChar));
@ -5717,7 +5717,7 @@ QString QString::fromLatin1(QByteArrayView ba)
} else if (ba.size() == 0) {
d = DataPointer::fromRawData(&_empty, 0);
} else {
d = DataPointer(Data::allocate(ba.size()), ba.size());
d = DataPointer(ba.size(), ba.size());
Q_CHECK_PTR(d.data());
d.data()[ba.size()] = '\0';
char16_t *dst = d.data();

View File

@ -236,7 +236,7 @@ public:
if (it == end)
return result;
QPodArrayOps<T> other{ Data::allocate(this->size), this->size };
QPodArrayOps<T> other(this->size, this->size);
Q_CHECK_PTR(other.data());
auto dest = other.begin();
// std::uninitialized_copy will fallback to ::memcpy/memmove()

View File

@ -52,6 +52,13 @@ public:
{
}
Q_NODISCARD_CTOR explicit
QArrayDataPointer(qsizetype alloc, qsizetype n = 0,
QArrayData::AllocationOption option = QArrayData::KeepSize)
: QArrayDataPointer(Data::allocate(alloc, option), n)
{
}
Q_NODISCARD_CTOR
static QArrayDataPointer fromRawData(const T *rawData, qsizetype length) noexcept
{
@ -326,11 +333,11 @@ public:
if constexpr (IsFwdIt) {
const qsizetype n = std::distance(first, last);
if (needsDetach() || n > constAllocatedCapacity()) {
QArrayDataPointer allocated(Data::allocate(detachCapacity(n)));
QArrayDataPointer allocated(detachCapacity(n));
swap(allocated);
}
} else if (needsDetach()) {
QArrayDataPointer allocated(Data::allocate(allocatedCapacity()));
QArrayDataPointer allocated(allocatedCapacity());
swap(allocated);
// We don't want to copy data that we know we'll overwrite
}

View File

@ -276,20 +276,20 @@ public:
public:
QList() = default;
explicit QList(qsizetype size)
: d(Data::allocate(size))
: d(size)
{
if (size)
d->appendInitialize(size);
}
QList(qsizetype size, parameter_type t)
: d(Data::allocate(size))
: d(size)
{
if (size)
d->copyAppend(size, t);
}
inline QList(std::initializer_list<T> args)
: d(Data::allocate(qsizetype(args.size())))
: d(qsizetype(args.size()))
{
if (args.size())
d->copyAppend(args.begin(), args.end());
@ -308,7 +308,7 @@ public:
} else {
const auto distance = std::distance(i1, i2);
if (distance) {
d = DataPointer(Data::allocate(qsizetype(distance)));
d = DataPointer(qsizetype(distance));
// appendIteratorRange can deal with contiguous iterators on its own,
// this is an optimization for C++17 code.
if constexpr (std::is_same_v<std::decay_t<InputIterator>, iterator> ||
@ -424,7 +424,7 @@ public:
return;
if (d->needsDetach()) {
// must allocate memory
DataPointer detached(Data::allocate(d.allocatedCapacity()));
DataPointer detached(d.allocatedCapacity());
d.swap(detached);
} else {
d->truncate(0);
@ -747,7 +747,7 @@ void QList<T>::reserve(qsizetype asize)
}
}
DataPointer detached(Data::allocate(qMax(asize, size())));
DataPointer detached(qMax(asize, size()));
detached->copyAppend(d->begin(), d->end());
if (detached.d_ptr())
detached->setFlag(Data::CapacityReserved);
@ -761,7 +761,7 @@ inline void QList<T>::squeeze()
return;
if (d->needsDetach() || size() < capacity()) {
// must allocate memory
DataPointer detached(Data::allocate(size()));
DataPointer detached(size());
if (size()) {
if (d.needsDetach())
detached->copyAppend(d.data(), d.data() + d.size);
@ -890,7 +890,7 @@ inline QList<T> &QList<T>::fill(parameter_type t, qsizetype newSize)
newSize = size();
if (d->needsDetach() || newSize > capacity()) {
// must allocate memory
DataPointer detached(Data::allocate(d->detachCapacity(newSize)));
DataPointer detached(d->detachCapacity(newSize));
detached->copyAppend(newSize, t);
d.swap(detached);
} else {
@ -972,7 +972,7 @@ inline QList<T> QList<T>::mid(qsizetype pos, qsizetype len) const
}
// Allocate memory
DataPointer copied(Data::allocate(l));
DataPointer copied(l);
copied->copyAppend(data() + p, data() + p + l);
return copied;
}

View File

@ -28,7 +28,7 @@ public:
}
explicit SimpleVector(size_t n, bool capacityReserved = false)
: d(Data::allocate(n))
: d(n)
{
if (n)
d->appendInitialize(n);
@ -37,7 +37,7 @@ public:
}
SimpleVector(size_t n, const T &t, bool capacityReserved = false)
: d(Data::allocate(n))
: d(n)
{
if (n)
d->copyAppend(n, t);
@ -46,7 +46,7 @@ public:
}
SimpleVector(const T *begin, const T *end, bool capacityReserved = false)
: d(Data::allocate(end - begin))
: d(end - begin)
{
if (end - begin)
d->copyAppend(begin, end);
@ -59,11 +59,6 @@ public:
{
}
explicit SimpleVector(QPair<Data*, T*> ptr, size_t len = 0)
: d(ptr, len)
{
}
SimpleVector(const QArrayDataPointer<T> &other)
: d(other)
{
@ -135,7 +130,7 @@ public:
}
}
SimpleVector detached(Data::allocate(qMax(n, size())));
SimpleVector detached(DataPointer(qMax(n, size())));
if (size()) {
detached.d->copyAppend(constBegin(), constEnd());
detached.d->setFlag(QArrayData::CapacityReserved);
@ -149,7 +144,7 @@ public:
return;
if (d->needsDetach() || newSize > capacity()) {
SimpleVector detached(Data::allocate(d->detachCapacity(newSize)));
SimpleVector detached(DataPointer(d->detachCapacity(newSize)));
if (newSize) {
if (newSize < size()) {
const T *const begin = constBegin();
@ -223,7 +218,7 @@ public:
const T *const end = begin + d->size;
if (d->needsDetach()) {
SimpleVector detached(Data::allocate(d->detachCapacity(size() - (last - first))));
SimpleVector detached(DataPointer(d->detachCapacity(size() - (last - first))));
if (first != begin)
detached.d->copyAppend(begin, first);
detached.d->copyAppend(last, end);

View File

@ -1116,8 +1116,7 @@ void tst_QArrayData::arrayOpsExtra()
const auto cloneArrayDataPointer = [] (auto &dataPointer, size_t capacity) {
using ArrayPointer = std::decay_t<decltype(dataPointer)>;
using Type = std::decay_t<typename ArrayPointer::parameter_type>;
ArrayPointer copy(QTypedArrayData<Type>::allocate(qsizetype(capacity)));
ArrayPointer copy{qsizetype(capacity)};
copy->copyAppend(dataPointer.begin(), dataPointer.end());
return copy;
};
@ -2037,7 +2036,7 @@ void tst_QArrayData::dataPointerAllocate()
const auto createDataPointer = [] (qsizetype capacity, auto initValue) {
using Type = std::decay_t<decltype(initValue)>;
Q_UNUSED(initValue);
return QArrayDataPointer<Type>(QTypedArrayData<Type>::allocate(capacity));
return QArrayDataPointer<Type>(capacity);
};
const auto testRealloc = [&] (qsizetype capacity, qsizetype newSize, auto initValue) {
@ -2453,7 +2452,7 @@ void tst_QArrayData::relocateWithExceptions()
};
const auto createDataPointer = [](qsizetype capacity, qsizetype initSize) {
QArrayDataPointer<ThrowingType> qadp(QTypedArrayData<ThrowingType>::allocate(capacity));
QArrayDataPointer<ThrowingType> qadp(capacity);
qadp->appendInitialize(initSize);
int i = 0;
std::generate(qadp.begin(), qadp.end(), [&i]() { return ThrowingType(i++); });