diff options
author | João Abecasis <joao.abecasis@nokia.com> | 2012-06-08 17:35:50 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-07-03 01:55:39 +0200 |
commit | deb8d178fe06e3f626f0e7152ac69504094a52a0 (patch) | |
tree | 91ded3353deedfdbe5ddc0023857e41672801229 | |
parent | 037238022f3a91a5619709b2c7cf4b38cd4d294b (diff) |
Add erase operation to QArrayDataOps
Change-Id: I37d3ac465f5beddb5038e22e9cda32acb16c78fc
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/tools/qarraydataops.h | 63 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qarraydata/simplevector.h | 26 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp | 53 |
3 files changed, 142 insertions, 0 deletions
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 <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> 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<int>) |