From deb8d178fe06e3f626f0e7152ac69504094a52a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Fri, 8 Jun 2012 17:35:50 +0200 Subject: [PATCH] Add erase operation to QArrayDataOps Change-Id: I37d3ac465f5beddb5038e22e9cda32acb16c78fc Reviewed-by: Thiago Macieira --- src/corelib/tools/qarraydataops.h | 63 +++++++++++++++++++ .../corelib/tools/qarraydata/simplevector.h | 26 ++++++++ .../tools/qarraydata/tst_qarraydata.cpp | 53 ++++++++++++++++ 3 files changed, 142 insertions(+) diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h index 088dd2bdee..e4da051742 100644 --- a/src/corelib/tools/qarraydataops.h +++ b/src/corelib/tools/qarraydataops.h @@ -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 @@ -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 @@ -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 diff --git a/tests/auto/corelib/tools/qarraydata/simplevector.h b/tests/auto/corelib/tools/qarraydata/simplevector.h index f708fc12d1..c2568cf29c 100644 --- a/tests/auto/corelib/tools/qarraydata/simplevector.h +++ b/tests/auto/corelib/tools/qarraydata/simplevector.h @@ -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); diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp index 9ab01d37ef..d3cc92080d 100644 --- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp +++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp @@ -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)