Introduce QArrayDataOps::truncate
This enables a truncating resize() to be implemented. It is similar to destroyAll(), but updates the size() as it goes, so it is safe to use outside a container's destructor (and doesn't necessarily destroy all elements). The appendInitialize test was repurposed and now doubles as an additional test for QArrayDataOps as well as exercising SimpleVector's resize(). Change-Id: Iee94a685c9ea436c6af5b1b77486734a38c49ca1 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
8c413f3eff
commit
15e3ae6b9d
@ -89,6 +89,14 @@ struct QPodArrayOps
|
||||
this->size += n;
|
||||
}
|
||||
|
||||
void truncate(size_t newSize)
|
||||
{
|
||||
Q_ASSERT(!this->ref.isShared());
|
||||
Q_ASSERT(newSize < size_t(this->size));
|
||||
|
||||
this->size = newSize;
|
||||
}
|
||||
|
||||
void destroyAll() // Call from destructors, ONLY!
|
||||
{
|
||||
Q_ASSERT(this->ref.atomic.load() == 0);
|
||||
@ -153,6 +161,17 @@ struct QGenericArrayOps
|
||||
}
|
||||
}
|
||||
|
||||
void truncate(size_t newSize)
|
||||
{
|
||||
Q_ASSERT(!this->ref.isShared());
|
||||
Q_ASSERT(newSize < size_t(this->size));
|
||||
|
||||
const T *const b = this->begin();
|
||||
do {
|
||||
(b + --this->size)->~T();
|
||||
} while (uint(this->size) != newSize);
|
||||
}
|
||||
|
||||
void destroyAll() // Call from destructors, ONLY
|
||||
{
|
||||
// As this is to be called only from destructor, it doesn't need to be
|
||||
@ -239,6 +258,7 @@ struct QMovableArrayOps
|
||||
{
|
||||
// using QGenericArrayOps<T>::appendInitialize;
|
||||
// using QGenericArrayOps<T>::copyAppend;
|
||||
// using QGenericArrayOps<T>::truncate;
|
||||
// using QGenericArrayOps<T>::destroyAll;
|
||||
|
||||
void insert(T *where, const T *b, const T *e)
|
||||
|
@ -170,6 +170,36 @@ public:
|
||||
detached.swap(*this);
|
||||
}
|
||||
|
||||
void resize(size_t newSize)
|
||||
{
|
||||
if (size() == newSize)
|
||||
return;
|
||||
|
||||
if (d->ref.isShared() || newSize > capacity()) {
|
||||
SimpleVector detached(Data::allocate(
|
||||
d->detachCapacity(newSize), d->detachFlags()));
|
||||
if (newSize) {
|
||||
if (newSize < size()) {
|
||||
const T *const begin = constBegin();
|
||||
detached.d->copyAppend(begin, begin + newSize);
|
||||
} else {
|
||||
if (size()) {
|
||||
const T *const begin = constBegin();
|
||||
detached.d->copyAppend(begin, begin + size());
|
||||
}
|
||||
detached.d->appendInitialize(newSize);
|
||||
}
|
||||
}
|
||||
detached.swap(*this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newSize > size())
|
||||
d->appendInitialize(newSize);
|
||||
else
|
||||
d->truncate(newSize);
|
||||
}
|
||||
|
||||
void prepend(const_iterator first, const_iterator last)
|
||||
{
|
||||
if (!d->size) {
|
||||
|
@ -81,7 +81,7 @@ private slots:
|
||||
void typedData();
|
||||
void gccBug43247();
|
||||
void arrayOps();
|
||||
void appendInitialize();
|
||||
void arrayOps2();
|
||||
void setSharable_data();
|
||||
void setSharable();
|
||||
void fromRawData();
|
||||
@ -1115,7 +1115,7 @@ void tst_QArrayData::arrayOps()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QArrayData::appendInitialize()
|
||||
void tst_QArrayData::arrayOps2()
|
||||
{
|
||||
CountedObject::LeakChecker leakChecker; Q_UNUSED(leakChecker)
|
||||
|
||||
@ -1137,6 +1137,69 @@ void tst_QArrayData::appendInitialize()
|
||||
QCOMPARE(vo[i].id, i);
|
||||
QCOMPARE(int(vo[i].flags), int(CountedObject::DefaultConstructed));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// appendInitialize, again
|
||||
|
||||
// These will detach
|
||||
vi.resize(10);
|
||||
vs.resize(10);
|
||||
vo.resize(10);
|
||||
|
||||
QCOMPARE(vi.size(), size_t(10));
|
||||
QCOMPARE(vs.size(), size_t(10));
|
||||
QCOMPARE(vo.size(), size_t(10));
|
||||
|
||||
QCOMPARE(CountedObject::liveCount, size_t(10));
|
||||
for (size_t i = 0; i < 5; ++i) {
|
||||
QCOMPARE(vi[i], 0);
|
||||
QVERIFY(vs[i].isNull());
|
||||
|
||||
QCOMPARE(vo[i].id, i);
|
||||
QCOMPARE(int(vo[i].flags), CountedObject::DefaultConstructed
|
||||
| CountedObject::CopyConstructed);
|
||||
}
|
||||
|
||||
for (size_t i = 5; i < 10; ++i) {
|
||||
QCOMPARE(vi[i], 0);
|
||||
QVERIFY(vs[i].isNull());
|
||||
|
||||
QCOMPARE(vo[i].id, i + 5);
|
||||
QCOMPARE(int(vo[i].flags), int(CountedObject::DefaultConstructed));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// truncate
|
||||
QVERIFY(!vi.isShared());
|
||||
QVERIFY(!vs.isShared());
|
||||
QVERIFY(!vo.isShared());
|
||||
|
||||
// These shouldn't detach
|
||||
vi.resize(7);
|
||||
vs.resize(7);
|
||||
vo.resize(7);
|
||||
|
||||
QCOMPARE(vi.size(), size_t(7));
|
||||
QCOMPARE(vs.size(), size_t(7));
|
||||
QCOMPARE(vo.size(), size_t(7));
|
||||
|
||||
QCOMPARE(CountedObject::liveCount, size_t(7));
|
||||
for (size_t i = 0; i < 5; ++i) {
|
||||
QCOMPARE(vi[i], 0);
|
||||
QVERIFY(vs[i].isNull());
|
||||
|
||||
QCOMPARE(vo[i].id, i);
|
||||
QCOMPARE(int(vo[i].flags), CountedObject::DefaultConstructed
|
||||
| CountedObject::CopyConstructed);
|
||||
}
|
||||
|
||||
for (size_t i = 5; i < 7; ++i) {
|
||||
QCOMPARE(vi[i], 0);
|
||||
QVERIFY(vs[i].isNull());
|
||||
|
||||
QCOMPARE(vo[i].id, i + 5);
|
||||
QCOMPARE(int(vo[i].flags), int(CountedObject::DefaultConstructed));
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(QArrayDataPointer<int>)
|
||||
|
Loading…
Reference in New Issue
Block a user