diff options
| -rw-r--r-- | src/corelib/tools/qarraydataops.h | 23 | ||||
| -rw-r--r-- | tests/auto/corelib/tools/qarraydata/simplevector.h | 7 | ||||
| -rw-r--r-- | tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp | 74 |
3 files changed, 103 insertions, 1 deletions
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h index 1b8ed3372d5..785a26c3a86 100644 --- a/src/corelib/tools/qarraydataops.h +++ b/src/corelib/tools/qarraydataops.h @@ -57,6 +57,16 @@ template <class T> struct QPodArrayOps : QTypedArrayData<T> { + void appendInitialize(size_t newSize) + { + Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(newSize > uint(this->size)); + Q_ASSERT(newSize <= this->alloc); + + ::memset(this->end(), 0, (newSize - this->size) * sizeof(T)); + this->size = newSize; + } + void copyAppend(const T *b, const T *e) { Q_ASSERT(!this->ref.isShared()); @@ -105,6 +115,18 @@ template <class T> struct QGenericArrayOps : QTypedArrayData<T> { + void appendInitialize(size_t newSize) + { + Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(newSize > uint(this->size)); + Q_ASSERT(newSize <= this->alloc); + + T *const begin = this->begin(); + do { + new (begin + this->size) T(); + } while (uint(++this->size) != newSize); + } + void copyAppend(const T *b, const T *e) { Q_ASSERT(!this->ref.isShared()); @@ -215,6 +237,7 @@ template <class T> struct QMovableArrayOps : QGenericArrayOps<T> { + // using QGenericArrayOps<T>::appendInitialize; // using QGenericArrayOps<T>::copyAppend; // using QGenericArrayOps<T>::destroyAll; diff --git a/tests/auto/corelib/tools/qarraydata/simplevector.h b/tests/auto/corelib/tools/qarraydata/simplevector.h index fe8108bff20..0cc7561b46b 100644 --- a/tests/auto/corelib/tools/qarraydata/simplevector.h +++ b/tests/auto/corelib/tools/qarraydata/simplevector.h @@ -63,6 +63,13 @@ public: { } + explicit SimpleVector(size_t n) + : d(Data::allocate(n)) + { + if (n) + d->appendInitialize(n); + } + SimpleVector(size_t n, const T &t) : d(Data::allocate(n)) { diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp index 4bd04f9bc32..6d3bbf046fd 100644 --- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp +++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp @@ -81,6 +81,7 @@ private slots: void typedData(); void gccBug43247(); void arrayOps(); + void appendInitialize(); void setSharable_data(); void setSharable(); void fromRawData(); @@ -894,11 +895,15 @@ struct CountedObject { CountedObject() : id(liveCount++) + , flags(DefaultConstructed) { } CountedObject(const CountedObject &other) : id(other.id) + , flags(other.flags == DefaultConstructed + ? ObjectFlags(CopyConstructed | DefaultConstructed) + : CopyConstructed) { ++liveCount; } @@ -910,6 +915,7 @@ struct CountedObject CountedObject &operator=(const CountedObject &other) { + flags = ObjectFlags(other.flags | CopyAssigned); id = other.id; return *this; } @@ -930,7 +936,15 @@ struct CountedObject const size_t previousLiveCount; }; + enum ObjectFlags { + DefaultConstructed = 1, + CopyConstructed = 2, + CopyAssigned = 4 + }; + size_t id; // not unique + ObjectFlags flags; + static size_t liveCount; }; @@ -968,7 +982,10 @@ void tst_QArrayData::arrayOps() for (int i = 0; i < 5; ++i) { QCOMPARE(vi[i], intArray[i]); QVERIFY(vs[i].isSharedWith(stringArray[i])); + QCOMPARE(vo[i].id, objArray[i].id); + QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed + | CountedObject::DefaultConstructed); } //////////////////////////////////////////////////////////////////////////// @@ -997,7 +1014,10 @@ void tst_QArrayData::arrayOps() for (int i = 0; i < 5; ++i) { QCOMPARE(vi[i], referenceInt); QVERIFY(vs[i].isSharedWith(referenceString)); + QCOMPARE(vo[i].id, referenceObject.id); + QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed + | CountedObject::DefaultConstructed); } //////////////////////////////////////////////////////////////////////////// @@ -1042,28 +1062,80 @@ void tst_QArrayData::arrayOps() QCOMPARE(vo.size(), size_t(30)); QCOMPARE(CountedObject::liveCount, size_t(36)); - for (int i = 0; i < 15; ++i) { + for (int i = 0; i < 5; ++i) { + QCOMPARE(vi[i], intArray[i % 5]); + QVERIFY(vs[i].isSharedWith(stringArray[i % 5])); + + QCOMPARE(vo[i].id, objArray[i % 5].id); + QCOMPARE(int(vo[i].flags), CountedObject::DefaultConstructed + | CountedObject::CopyAssigned); + } + + for (int i = 5; i < 15; ++i) { QCOMPARE(vi[i], intArray[i % 5]); QVERIFY(vs[i].isSharedWith(stringArray[i % 5])); + QCOMPARE(vo[i].id, objArray[i % 5].id); + QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed + | CountedObject::CopyAssigned); } for (int i = 15; i < 20; ++i) { QCOMPARE(vi[i], referenceInt); QVERIFY(vs[i].isSharedWith(referenceString)); + QCOMPARE(vo[i].id, referenceObject.id); + QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed + | CountedObject::CopyAssigned); } for (int i = 20; i < 25; ++i) { QCOMPARE(vi[i], intArray[i % 5]); QVERIFY(vs[i].isSharedWith(stringArray[i % 5])); + QCOMPARE(vo[i].id, objArray[i % 5].id); + + // Originally inserted as (DefaultConstructed | CopyAssigned), later + // get shuffled into place by std::rotate (SimpleVector::insert, + // overlapping mode). + // Depending on implementation of rotate, final assignment can be: + // - straight from source: DefaultConstructed | CopyAssigned + // - through a temporary: CopyConstructed | CopyAssigned + QCOMPARE(vo[i].flags & CountedObject::CopyAssigned, + int(CountedObject::CopyAssigned)); } for (int i = 25; i < 30; ++i) { QCOMPARE(vi[i], referenceInt); QVERIFY(vs[i].isSharedWith(referenceString)); + QCOMPARE(vo[i].id, referenceObject.id); + QCOMPARE(int(vo[i].flags), CountedObject::CopyConstructed + | CountedObject::CopyAssigned); + } +} + +void tst_QArrayData::appendInitialize() +{ + CountedObject::LeakChecker leakChecker; Q_UNUSED(leakChecker) + + //////////////////////////////////////////////////////////////////////////// + // appendInitialize + SimpleVector<int> vi(5); + SimpleVector<QString> vs(5); + SimpleVector<CountedObject> vo(5); + + QCOMPARE(vi.size(), size_t(5)); + QCOMPARE(vs.size(), size_t(5)); + QCOMPARE(vo.size(), size_t(5)); + + QCOMPARE(CountedObject::liveCount, size_t(5)); + 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), int(CountedObject::DefaultConstructed)); } } |
