Add erase operation to QArrayDataOps

Change-Id: I37d3ac465f5beddb5038e22e9cda32acb16c78fc
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
João Abecasis 2012-06-08 17:35:50 +02:00 committed by Qt by Nokia
parent 037238022f
commit deb8d178fe
3 changed files with 142 additions and 0 deletions

View File

@ -117,6 +117,16 @@ struct QPodArrayOps
::memcpy(where, b, (e - b) * sizeof(T));
this->size += (e - b);
}
void erase(T *b, T *e)
{
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e < this->end());
::memmove(b, e, (this->end() - e) * sizeof(T));
this->size -= (e - b);
}
};
template <class T>
@ -250,6 +260,25 @@ struct QGenericArrayOps
*writeIter = *e;
}
}
void erase(T *b, T *e)
{
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e < this->end());
const T *const end = this->end();
do {
*b = *e;
++b, ++e;
} while (e != end);
do {
(--e)->~T();
--this->size;
} while (e != b);
}
};
template <class T>
@ -324,6 +353,40 @@ struct QMovableArrayOps
displace.commit();
this->size += (e - b);
}
void erase(T *b, T *e)
{
Q_ASSERT(b < e);
Q_ASSERT(b >= this->begin() && b < this->end());
Q_ASSERT(e > this->begin() && e < this->end());
struct Mover
{
Mover(T *&start, const T *finish, int &sz)
: destination(start)
, source(start)
, n(finish - start)
, size(sz)
{
}
~Mover()
{
::memmove(destination, source, n * sizeof(T));
size -= (source - destination);
}
T *&destination;
const T *const source;
size_t n;
int &size;
} mover(e, this->end(), this->size);
do {
// Exceptions or not, dtor called once per instance
(--e)->~T();
} while (e != b);
}
};
template <class T, class = void>

View File

@ -302,6 +302,32 @@ public:
d->insert(where, first, last);
}
void erase(iterator first, iterator last)
{
if (first == last)
return;
const T *const begin = d->begin();
const T *const end = begin + d->size;
if (d.needsDetach()) {
SimpleVector detached(Data::allocate(
d->detachCapacity(size() - (last - first)),
d->detachFlags()));
if (first != begin)
detached.d->copyAppend(begin, first);
detached.d->copyAppend(last, end);
detached.swap(*this);
return;
}
if (last == end)
d->truncate(end - first);
else
d->erase(first, last);
}
void swap(SimpleVector &other)
{
qSwap(d, other.d);

View File

@ -1222,6 +1222,59 @@ void tst_QArrayData::arrayOps2()
QCOMPARE(vo[i].id, i + 5);
QCOMPARE(int(vo[i].flags), int(CountedObject::DefaultConstructed));
}
////////////////////////////////////////////////////////////////////////////
vi.resize(10);
vs.resize(10);
vo.resize(10);
for (size_t i = 7; i < 10; ++i) {
vi[i] = i;
vs[i] = QString::number(i);
QCOMPARE(vo[i].id, i);
QCOMPARE(int(vo[i].flags), int(CountedObject::DefaultConstructed));
}
QCOMPARE(CountedObject::liveCount, size_t(10));
////////////////////////////////////////////////////////////////////////////
// erase
vi.erase(vi.begin() + 2, vi.begin() + 5);
vs.erase(vs.begin() + 2, vs.begin() + 5);
vo.erase(vo.begin() + 2, vo.begin() + 5);
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 < 2; ++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 = 2; i < 4; ++i) {
QCOMPARE(vi[i], 0);
QVERIFY(vs[i].isNull());
QCOMPARE(vo[i].id, i + 8);
QCOMPARE(int(vo[i].flags), int(CountedObject::DefaultConstructed)
| CountedObject::CopyAssigned);
}
for (size_t i = 4; i < 7; ++i) {
QCOMPARE(vi[i], int(i + 3));
QCOMPARE(vs[i], QString::number(i + 3));
QCOMPARE(vo[i].id, i + 3);
QCOMPARE(int(vo[i].flags), CountedObject::DefaultConstructed
| CountedObject::CopyAssigned);
}
}
Q_DECLARE_METATYPE(QArrayDataPointer<int>)