summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJędrzej Nowacki <jedrzej.nowacki@nokia.com>2012-04-26 12:06:17 +0200
committerQt by Nokia <qt-info@nokia.com>2012-05-30 17:07:27 +0200
commitd17cf14185eb84863549e0119c8b7bd20db78580 (patch)
tree843efdf2b591293fabf8c5a7cf448d9514f35495
parent5131aefc1f0c04936e3ef19c9870d884775471e5 (diff)
Implement QVector with QArrayData interface.
Change-Id: I109f46892aed2f6024459812d24922b12358814d Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/tools/qarraydata.h12
-rw-r--r--src/corelib/tools/qvector.cpp34
-rw-r--r--src/corelib/tools/qvector.h483
-rw-r--r--src/gui/painting/qregion.cpp2
-rw-r--r--tests/auto/corelib/tools/qvector/tst_qvector.cpp1486
-rw-r--r--tests/benchmarks/corelib/tools/qvector/outofline.cpp33
-rw-r--r--tests/benchmarks/corelib/tools/qvector/qrawvector.h26
-rw-r--r--tests/benchmarks/corelib/tools/qvector/qvector.pro2
8 files changed, 1695 insertions, 383 deletions
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index b038e855ac..ae78fec4e8 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -179,6 +179,18 @@ struct QTypedArrayData
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
return static_cast<QTypedArrayData *>(QArrayData::sharedNull());
}
+
+ static QTypedArrayData *sharedEmpty()
+ {
+ Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
+ return allocate(/* capacity */ 0);
+ }
+
+ static QTypedArrayData *unsharableEmpty()
+ {
+ Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
+ return allocate(/* capacity */ 0, Unsharable);
+ }
};
template <class T, size_t N>
diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp
index 329727c8ea..a19599e861 100644
--- a/src/corelib/tools/qvector.cpp
+++ b/src/corelib/tools/qvector.cpp
@@ -47,40 +47,6 @@
QT_BEGIN_NAMESPACE
-static inline int alignmentThreshold()
-{
- // malloc on 32-bit platforms should return pointers that are 8-byte aligned or more
- // while on 64-bit platforms they should be 16-byte aligned or more
- return 2 * sizeof(void*);
-}
-
-const QVectorData QVectorData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, 0 };
-
-QVectorData *QVectorData::allocate(int size, int alignment)
-{
- return static_cast<QVectorData *>(alignment > alignmentThreshold() ? qMallocAligned(size, alignment) : ::malloc(size));
-}
-
-QVectorData *QVectorData::reallocate(QVectorData *x, int newsize, int oldsize, int alignment)
-{
- if (alignment > alignmentThreshold())
- return static_cast<QVectorData *>(qReallocAligned(x, newsize, oldsize, alignment));
- return static_cast<QVectorData *>(realloc(x, newsize));
-}
-
-void QVectorData::free(QVectorData *x, int alignment)
-{
- if (alignment > alignmentThreshold())
- qFreeAligned(x);
- else
- ::free(x);
-}
-
-int QVectorData::grow(int sizeOfHeader, int size, int sizeOfT)
-{
- return qAllocMore(size * sizeOfT, sizeOfHeader) / sizeOfT;
-}
-
/*!
\class QVector
\brief The QVector class is a template class that provides a dynamic array.
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 60cf12e60d..5b2cc11ed1 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -46,6 +46,7 @@
#include <QtCore/qiterator.h>
#include <QtCore/qlist.h>
#include <QtCore/qrefcount.h>
+#include <QtCore/qarraydata.h>
#include <iterator>
#include <vector>
@@ -59,59 +60,19 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-
-struct Q_CORE_EXPORT QVectorData
-{
- QtPrivate::RefCount ref;
- int size;
- uint alloc : 31;
- uint capacityReserved : 1;
-
- qptrdiff offset;
-
- void* data() { return reinterpret_cast<char *>(this) + this->offset; }
-
- static const QVectorData shared_null;
- static QVectorData *allocate(int size, int alignment);
- static QVectorData *reallocate(QVectorData *old, int newsize, int oldsize, int alignment);
- static void free(QVectorData *data, int alignment);
- static int grow(int sizeOfHeader, int size, int sizeOfT);
-};
-
-template <typename T>
-struct QVectorTypedData : QVectorData
-{
- T* begin() { return reinterpret_cast<T *>(this->data()); }
- T* end() { return begin() + this->size; }
-
- static QVectorTypedData *sharedNull() { return static_cast<QVectorTypedData *>(const_cast<QVectorData *>(&QVectorData::shared_null)); }
-};
-
class QRegion;
template <typename T>
class QVector
{
- typedef QVectorTypedData<T> Data;
+ typedef QTypedArrayData<T> Data;
Data *d;
public:
inline QVector() : d(Data::sharedNull()) { }
explicit QVector(int size);
QVector(int size, const T &t);
- inline QVector(const QVector<T> &v)
- {
- if (v.d->ref.ref()) {
- d = v.d;
- } else {
- d = Data::sharedNull();
- realloc(0, int(v.d->alloc));
- qCopy(v.d->begin(), v.d->end(), d->begin());
- d->size = v.d->size;
- d->capacityReserved = v.d->capacityReserved;
- }
- }
-
+ inline QVector(const QVector<T> &v);
inline ~QVector() { if (!d->ref.deref()) free(d); }
QVector<T> &operator=(const QVector<T> &v);
#ifdef Q_COMPILER_RVALUE_REFS
@@ -134,9 +95,17 @@ public:
inline int capacity() const { return int(d->alloc); }
void reserve(int size);
- inline void squeeze() { realloc(d->size, d->size); d->capacityReserved = 0; }
+ inline void squeeze()
+ {
+ realloc(d->size, d->size);
+ if (d->capacityReserved) {
+ // capacity reserved in a read only memory would be useless
+ // this checks avoid writing to such memory.
+ d->capacityReserved = 0;
+ }
+ }
- inline void detach() { if (!isDetached()) detach_helper(); }
+ inline void detach();
inline bool isDetached() const { return !d->ref.isShared(); }
inline void setSharable(bool sharable)
{
@@ -144,8 +113,14 @@ public:
return;
if (!sharable)
detach();
- if (d != Data::sharedNull())
+
+ if (d == Data::unsharableEmpty()) {
+ if (sharable)
+ d = Data::sharedNull();
+ } else {
d->ref.setSharable(sharable);
+ }
+ Q_ASSERT(d->ref.isSharable() == sharable);
}
inline bool isSharedWith(const QVector<T> &other) const { return d == other.d; }
@@ -314,35 +289,107 @@ public:
private:
friend class QRegion; // Optimization for QRegion::rects()
- void detach_helper();
- Data *malloc(int alloc);
- void realloc(int size, int alloc);
+ void realloc(const int size, const int alloc, QArrayData::AllocationOptions options = QArrayData::Default);
void free(Data *d);
+ void defaultConstruct(T *from, T *to);
+ void copyConstruct(T *srcFrom, T *srcTo, T *dstFrom);
+ void destruct(T *from, T *to);
- class AlignmentDummy { QVectorData header; T array[1]; };
+ class AlignmentDummy { Data header; T array[1]; };
+};
- static Q_DECL_CONSTEXPR int offsetOfTypedData()
- {
- // (non-POD)-safe offsetof(AlignmentDummy, array)
- return (sizeof(QVectorData) + (alignOfTypedData() - 1)) & ~(alignOfTypedData() - 1);
+template <typename T>
+void QVector<T>::defaultConstruct(T *from, T *to)
+{
+ if (QTypeInfo<T>::isComplex) {
+ while (from != to) {
+ new (from++) T();
+ }
+ } else {
+ ::memset(from, 0, (to - from) * sizeof(T));
}
- static Q_DECL_CONSTEXPR int alignOfTypedData()
- {
- return Q_ALIGNOF(AlignmentDummy);
+}
+
+template <typename T>
+void QVector<T>::copyConstruct(T *srcFrom, T *srcTo, T *dstFrom)
+{
+ if (QTypeInfo<T>::isComplex) {
+ while (srcFrom != srcTo)
+ new (dstFrom++) T(*srcFrom++);
+ } else {
+ ::memcpy(dstFrom, srcFrom, (srcTo - srcFrom) * sizeof(T));
}
-};
+}
+
+template <typename T>
+void QVector<T>::destruct(T *from, T *to)
+{
+ if (QTypeInfo<T>::isComplex) {
+ while (from != to) {
+ from++->~T();
+ }
+ }
+}
+
+template <typename T>
+inline QVector<T>::QVector(const QVector<T> &v)
+{
+ if (v.d->ref.ref()) {
+ d = v.d;
+ } else {
+ if (v.d->capacityReserved) {
+ d = Data::allocate(v.d->alloc);
+ d->capacityReserved = true;
+ } else {
+ d = Data::allocate(v.d->size);
+ }
+ if (d->alloc) {
+ copyConstruct(v.d->begin(), v.d->end(), d->begin());
+ d->size = v.d->size;
+ }
+ }
+}
template <typename T>
-void QVector<T>::detach_helper()
-{ realloc(d->size, int(d->alloc)); }
+void QVector<T>::detach()
+{
+ if (!isDetached()) {
+ if (d->alloc)
+ realloc(d->size, int(d->alloc));
+ else
+ d = Data::unsharableEmpty();
+ }
+ Q_ASSERT(isDetached());
+}
+
template <typename T>
void QVector<T>::reserve(int asize)
-{ if (asize > int(d->alloc)) realloc(d->size, asize); if (isDetached()) d->capacityReserved = 1; }
+{
+ if (asize > int(d->alloc))
+ realloc(d->size, asize);
+ if (isDetached())
+ d->capacityReserved = 1;
+ Q_ASSERT(capacity() >= asize);
+}
+
template <typename T>
void QVector<T>::resize(int asize)
-{ realloc(asize, (asize > int(d->alloc) || (!d->capacityReserved && asize < d->size && asize < int(d->alloc >> 1))) ?
- QVectorData::grow(offsetOfTypedData(), asize, sizeof(T))
- : int(d->alloc)); }
+{
+ int newAlloc;
+ const int oldAlloc = int(d->alloc);
+ QArrayData::AllocationOptions opt;
+
+ if (asize > oldAlloc) { // there is not enough space
+ newAlloc = asize;
+ opt = QArrayData::Grow;
+ } else if (!d->capacityReserved && asize < d->size && asize < (oldAlloc >> 1)) { // we want to shrink
+ newAlloc = asize;
+ opt = QArrayData::Grow;
+ } else {
+ newAlloc = oldAlloc;
+ }
+ realloc(asize, newAlloc, opt);
+}
template <typename T>
inline void QVector<T>::clear()
{ *this = QVector<T>(); }
@@ -397,44 +444,29 @@ QVector<T> &QVector<T>::operator=(const QVector<T> &v)
}
template <typename T>
-inline typename QVector<T>::Data *QVector<T>::malloc(int aalloc)
-{
- QVectorData *vectordata = QVectorData::allocate(offsetOfTypedData() + aalloc * sizeof(T), alignOfTypedData());
- Q_CHECK_PTR(vectordata);
- return static_cast<Data *>(vectordata);
-}
-
-template <typename T>
QVector<T>::QVector(int asize)
{
- d = malloc(asize);
- d->ref.initializeOwned();
- d->size = asize;
- d->alloc = uint(d->size);
- d->capacityReserved = false;
- d->offset = offsetOfTypedData();
- if (QTypeInfo<T>::isComplex) {
- T* b = d->begin();
- T* i = d->end();
- while (i != b)
- new (--i) T;
+ if (Q_LIKELY(asize)) {
+ d = Data::allocate(asize);
+ d->size = asize;
+ defaultConstruct(d->begin(), d->end());
} else {
- memset(d->begin(), 0, asize * sizeof(T));
+ d = Data::sharedNull();
}
}
template <typename T>
QVector<T>::QVector(int asize, const T &t)
{
- d = malloc(asize);
- d->ref.initializeOwned();
- d->size = asize;
- d->alloc = uint(d->size);
- d->capacityReserved = false;
- d->offset = offsetOfTypedData();
- T* i = d->end();
- while (i != d->begin())
- new (--i) T(t);
+ if (asize) {
+ d = Data::allocate(asize);
+ d->size = asize;
+ T* i = d->end();
+ while (i != d->begin())
+ new (--i) T(t);
+ } else {
+ d = Data::sharedNull();
+ }
}
#ifdef Q_COMPILER_INITIALIZER_LISTS
@@ -442,120 +474,114 @@ template <typename T>
QVector<T>::QVector(std::initializer_list<T> args)
{
d = malloc(int(args.size()));
- d->ref.initializeOwned();
+ // std::initializer_list<T>::iterator is guaranteed to be
+ // const T* ([support.initlist]/1), so can be memcpy'ed away from by copyConstruct
+ copyConstruct(args.begin(), args.end(), d->begin());
d->size = int(args.size());
- d->alloc = uint(d->size);
- d->capacityReserved = false;
- d->offset = offsetOfTypedData();
- if (QTypeInfo<T>::isComplex) {
- T* b = d->begin();
- T* i = d->end();
- const T* s = args.end();
- while (i != b)
- new(--i) T(*--s);
- } else {
- // std::initializer_list<T>::iterator is guaranteed to be
- // const T* ([support.initlist]/1), so can be memcpy'ed away from:
- ::memcpy(d->begin(), args.begin(), args.size() * sizeof(T));
- }
}
#endif
template <typename T>
void QVector<T>::free(Data *x)
{
- if (QTypeInfo<T>::isComplex) {
- T* b = x->begin();
- T* i = b + x->size;
- while (i-- != b)
- i->~T();
- }
- Data::free(x, alignOfTypedData());
+ destruct(x->begin(), x->end());
+ Data::deallocate(x);
}
template <typename T>
-void QVector<T>::realloc(int asize, int aalloc)
+void QVector<T>::realloc(const int asize, const int aalloc, QArrayData::AllocationOptions options)
{
- Q_ASSERT(asize <= aalloc);
- T *pOld;
- T *pNew;
+ Q_ASSERT(asize >= 0 && asize <= aalloc);
Data *x = d;
- if (QTypeInfo<T>::isComplex && asize < d->size && isDetached()) {
- // call the destructor on all objects that need to be
- // destroyed when shrinking
- pOld = d->begin() + d->size;
- pNew = d->begin() + asize;
- while (asize < d->size) {
- (--pOld)->~T();
- d->size--;
- }
- }
-
- if (aalloc != int(d->alloc) || !isDetached()) {
- // (re)allocate memory
- if (QTypeInfo<T>::isStatic) {
- x = malloc(aalloc);
- Q_CHECK_PTR(x);
- x->size = 0;
- } else if (!isDetached()) {
- x = malloc(aalloc);
- Q_CHECK_PTR(x);
- if (QTypeInfo<T>::isComplex) {
- x->size = 0;
- } else {
- ::memcpy(x, d, offsetOfTypedData() + qMin(uint(aalloc), d->alloc) * sizeof(T));
- x->size = d->size;
+ const bool isShared = d->ref.isShared();
+#ifndef QT_NO_DEBUG
+ bool moved = false;
+ int oldSize = d->size;
+#endif
+ if (aalloc != 0) {
+ if (aalloc != int(d->alloc) || isShared) {
+ QT_TRY {
+ // allocate memory
+ x = Data::allocate(aalloc, options);
+ Q_CHECK_PTR(x);
+ // aalloc is bigger then 0 so it is not [un]sharedEmpty
+ Q_ASSERT(x->ref.isSharable() || options.testFlag(QArrayData::Unsharable));
+ Q_ASSERT(!x->ref.isStatic());
+ x->size = asize;
+
+ T *srcBegin = d->begin();
+ T *srcEnd = asize > d->size ? d->end() : d->begin() + asize;
+ T *dst = x->begin();
+
+ if (QTypeInfo<T>::isStatic || (isShared && QTypeInfo<T>::isComplex)) {
+ // we can not move the data, we need to copy construct it
+ while (srcBegin != srcEnd) {
+ new (dst++) T(*srcBegin++);
+ }
+ } else {
+ ::memcpy(dst, srcBegin, (srcEnd - srcBegin) * sizeof(T));
+ dst += srcEnd - srcBegin;
+
+ // destruct unused / not moved data
+ if (asize < d->size)
+ destruct(d->begin() + asize, d->end());
+#ifndef QT_NO_DEBUG
+ moved = true;
+#endif
+ }
+
+ if (asize > d->size) {
+ // construct all new objects when growing
+ QT_TRY {
+ defaultConstruct(dst, x->end());
+ } QT_CATCH (...) {
+ // destruct already copied objects
+ destruct(x->begin(), dst);
+ QT_RETHROW;
+ }
+ }
+ } QT_CATCH (...) {
+ Data::deallocate(x);
+ QT_RETHROW;
}
+ x->capacityReserved = d->capacityReserved;
} else {
- QT_TRY {
- QVectorData *mem = QVectorData::reallocate(d, offsetOfTypedData() + aalloc * sizeof(T),
- offsetOfTypedData() + d->alloc * sizeof(T), alignOfTypedData());
- Q_CHECK_PTR(mem);
- x = d = static_cast<Data *>(mem);
- x->size = d->size;
- } QT_CATCH (const std::bad_alloc &) {
- if (aalloc > int(d->alloc)) // ignore the error in case we are just shrinking.
- QT_RETHROW;
+ Q_ASSERT(d->alloc == aalloc); // resize, without changing allocation size
+ Q_ASSERT(isDetached()); // can be done only on detached d
+ Q_ASSERT(x == d); // in this case we do not need to allocate anything
+ if (asize <= d->size) {
+ destruct(x->begin() + asize, x->end()); // from future end to current end
+ } else {
+ defaultConstruct(x->end(), x->begin() + asize); // from current end to future end
}
+ x->size = asize;
}
- x->ref.initializeOwned();
- x->alloc = uint(aalloc);
- x->capacityReserved = d->capacityReserved;
- x->offset = offsetOfTypedData();
+ } else {
+ x = Data::sharedNull();
}
-
- if (QTypeInfo<T>::isComplex) {
- QT_TRY {
- pOld = d->begin() + x->size;
- pNew = x->begin() + x->size;
- // copy objects from the old array into the new array
- const int toMove = qMin(asize, d->size);
- while (x->size < toMove) {
- new (pNew++) T(*pOld++);
- x->size++;
- }
- // construct all new objects when growing
- while (x->size < asize) {
- new (pNew++) T;
- x->size++;
+ if (d != x) {
+ if (!d->ref.deref()) {
+ Q_ASSERT(!isShared);
+ Q_ASSERT(d->size == oldSize);
+ if (QTypeInfo<T>::isStatic || !aalloc) {
+ // data was copy constructed, we need to call destructors
+ // or if !alloc we did nothing to the old 'd'.
+ Q_ASSERT(!moved);
+ free(d);
+ } else {
+ Data::deallocate(d);
}
- } QT_CATCH (...) {
- free(x);
- QT_RETHROW;
}
-
- } else if (asize > x->size) {
- // initialize newly allocated memory to 0
- memset(x->end(), 0, (asize - x->size) * sizeof(T));
- }
- x->size = asize;
-
- if (d != x) {
- if (!d->ref.deref())
- free(d);
d = x;
}
+
+ Q_ASSERT(d->data());
+ Q_ASSERT(d->size <= d->alloc);
+ Q_ASSERT(d != Data::unsharableEmpty());
+ Q_ASSERT(aalloc ? d != Data::sharedNull() : d == Data::sharedNull());
+ Q_ASSERT(d->alloc >= aalloc);
+ Q_ASSERT(d->size == asize);
}
template<typename T>
@@ -575,21 +601,16 @@ Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
template <typename T>
void QVector<T>::append(const T &t)
{
- if (!isDetached() || d->size + 1 > int(d->alloc)) {
- const T copy(t);
- realloc(d->size, (d->size + 1 > int(d->alloc)) ?
- QVectorData::grow(offsetOfTypedData(), d->size + 1, sizeof(T))
- : int(d->alloc));
- if (QTypeInfo<T>::isComplex)
- new (d->end()) T(copy);
- else
- *d->end() = copy;
- } else {
- if (QTypeInfo<T>::isComplex)
- new (d->end()) T(t);
- else
- *d->end() = t;
+ const T copy(t);
+ const bool isTooSmall = uint(d->size + 1) > d->alloc;
+ if (!isDetached() || isTooSmall) {
+ QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
+ realloc(d->size, isTooSmall ? d->size + 1 : d->alloc, opt);
}
+ if (QTypeInfo<T>::isComplex)
+ new (d->end()) T(copy);
+ else
+ *d->end() = copy;
++d->size;
}
@@ -600,7 +621,7 @@ typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, c
if (n != 0) {
const T copy(t);
if (!isDetached() || d->size + n > int(d->alloc))
- realloc(d->size, QVectorData::grow(offsetOfTypedData(), d->size + n, sizeof(T)));
+ realloc(d->size, d->size + n, QArrayData::Grow);
if (QTypeInfo<T>::isStatic) {
T *b = d->end();
T *i = d->end() + n;
@@ -629,23 +650,37 @@ typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, c
template <typename T>
typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
{
- int f = int(abegin - d->begin());
- int l = int(aend - d->begin());
- int n = l - f;
- detach();
- if (QTypeInfo<T>::isComplex) {
- qCopy(d->begin()+l, d->end(), d->begin()+f);
- T *i = d->end();
- T* b = d->end()-n;
- while (i != b) {
- --i;
- i->~T();
+ abegin = qMax(abegin, d->begin());
+ aend = qMin(aend, d->end());
+
+ Q_ASSERT(abegin <= aend);
+
+ const int itemsToErase = aend - abegin;
+ const int itemsUntouched = abegin - d->begin();
+
+ // FIXME we could do a proper realloc, which copy constructs only needed data.
+ // FIXME we ara about to delete data maybe it is good time to shrink?
+ if (d->alloc) {
+ detach();
+ if (QTypeInfo<T>::isStatic) {
+ iterator moveBegin = abegin + itemsToErase;
+ iterator moveEnd = d->end();
+ while (moveBegin != moveEnd) {
+ if (QTypeInfo<T>::isComplex)
+ abegin->~T();
+ new (abegin++) T(*moveBegin++);
+ }
+ if (abegin < d->end()) {
+ // destroy rest of instances
+ destruct(abegin, d->end());
+ }
+ } else {
+ destruct(abegin, aend);
+ memmove(abegin, aend, (d->size - itemsToErase - itemsUntouched) * sizeof(T));
}
- } else {
- memmove(d->begin() + f, d->begin() + l, (d->size-l)*sizeof(T));
+ d->size -= itemsToErase;
}
- d->size -= n;
- return d->begin() + f;
+ return d->begin() + itemsUntouched;
}
template <typename T>
@@ -684,16 +719,18 @@ QVector<T> &QVector<T>::operator+=(const QVector &l)
int newSize = d->size + l.d->size;
realloc(d->size, newSize);
- T *w = d->begin() + newSize;
- T *i = l.d->end();
- T *b = l.d->begin();
- while (i != b) {
- if (QTypeInfo<T>::isComplex)
- new (--w) T(*--i);
- else
- *--w = *--i;
+ if (d->alloc) {
+ T *w = d->begin() + newSize;
+ T *i = l.d->end();
+ T *b = l.d->begin();
+ while (i != b) {
+ if (QTypeInfo<T>::isComplex)
+ new (--w) T(*--i);
+ else
+ *--w = *--i;
+ }
+ d->size = newSize;
}
- d->size = newSize;
return *this;
}
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 8ecb122762..db20d10e5a 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -4217,7 +4217,7 @@ QVector<QRect> QRegion::rects() const
if (d->qt_rgn) {
d->qt_rgn->vectorize();
// hw: modify the vector size directly to avoid reallocation
- if (d->qt_rgn->rects.d != &QVectorData::shared_null)
+ if (d->qt_rgn->rects.d != QVector<QRect>::Data::sharedNull())
d->qt_rgn->rects.d->size = d->qt_rgn->numRects;
return d->qt_rgn->rects;
} else {
diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
index 67ca547736..56570b8e53 100644
--- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp
+++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
@@ -42,24 +42,181 @@
#include <QtTest/QtTest>
#include <qvector.h>
+struct Movable {
+ Movable(char input = 'j')
+ : i(input)
+ , state(Constructed)
+ {
+ ++counter;
+ }
+ Movable(const Movable &other)
+ : i(other.i)
+ , state(Constructed)
+ {
+ check(other.state, Constructed);
+ ++counter;
+ }
+
+ ~Movable()
+ {
+ check(state, Constructed);
+ i = 0;
+ --counter;
+ state = Destructed;
+ }
+
+ bool operator ==(const Movable &other) const
+ {
+ check(state, Constructed);
+ check(other.state, Constructed);
+ return i == other.i;
+ }
+
+ Movable &operator=(const Movable &other)
+ {
+ check(state, Constructed);
+ check(other.state, Constructed);
+ i = other.i;
+ return *this;
+ }
+ char i;
+ static int counter;
+private:
+ enum State { Constructed = 106, Destructed = 110 };
+ State state;
+
+ static void check(const State state1, const State state2)
+ {
+ QCOMPARE(state1, state2);
+ }
+};
+
+int Movable::counter = 0;
+QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
+Q_DECLARE_METATYPE(Movable);
+
+struct Custom {
+ Custom(char input = 'j')
+ : i(input)
+ , that(this)
+ , state(Constructed)
+ {
+ ++counter;
+ }
+ Custom(const Custom &other)
+ : that(this)
+ , state(Constructed)
+ {
+ check(&other);
+ ++counter;
+ this->i = other.i;
+ }
+ ~Custom()
+ {
+ check(this);
+ i = 0;
+ --counter;
+ state = Destructed;
+ }
+
+ bool operator ==(const Custom &other) const
+ {
+ check(&other);
+ check(this);
+ return i == other.i;
+ }
+
+ Custom &operator=(const Custom &other)
+ {
+ check(&other);
+ check(this);
+ i = other.i;
+ return *this;
+ }
+ static int counter;
+
+ char i; // used to identify orgin of an instance
+private:
+ Custom *that; // used to check if an instance was moved
+
+ enum State { Constructed = 106, Destructed = 110 };
+ State state;
+
+ static void check(const Custom *c)
+ {
+ // check if c object has been moved
+ QCOMPARE(c, c->that);
+ QCOMPARE(c->state, Constructed);
+ }
+};
+int Custom::counter = 0;
+
+Q_DECLARE_METATYPE(Custom);
+
+// tests depends on the fact that:
+Q_STATIC_ASSERT(!QTypeInfo<int>::isStatic);
+Q_STATIC_ASSERT(!QTypeInfo<int>::isComplex);
+Q_STATIC_ASSERT(!QTypeInfo<Movable>::isStatic);
+Q_STATIC_ASSERT(QTypeInfo<Movable>::isComplex);
+Q_STATIC_ASSERT(QTypeInfo<Custom>::isStatic);
+Q_STATIC_ASSERT(QTypeInfo<Custom>::isComplex);
+
+
class tst_QVector : public QObject
{
Q_OBJECT
private slots:
- void constructors() const;
- void append() const;
+ void constructors_empty() const;
+ void constructors_emptyReserveZero() const;
+ void constructors_emptyReserve() const;
+ void constructors_reserveAndInitialize() const;
+ void copyConstructorInt() const;
+ void copyConstructorMovable() const;
+ void copyConstructorCustom() const;
+ void addInt() const;
+ void addMovable() const;
+ void addCustom() const;
+ void appendInt() const;
+ void appendMovable() const;
+ void appendCustom() const;
void at() const;
- void capacity() const;
- void clear() const;
+ void capacityInt() const;
+ void capacityMovable() const;
+ void capacityCustom() const;
+ void clearInt() const;
+ void clearMovable() const;
+ void clearCustom() const;
void constData() const;
void contains() const;
- void count() const;
+ void countInt() const;
+ void countMovable() const;
+ void countCustom() const;
void data() const;
- void empty() const;
+ void emptyInt() const;
+ void emptyMovable() const;
+ void emptyCustom() const;
void endsWith() const;
- void fill() const;
+ void eraseEmptyInt() const;
+ void eraseEmptyMovable() const;
+ void eraseEmptyCustom() const;
+ void eraseEmptyReservedInt() const;
+ void eraseEmptyReservedMovable() const;
+ void eraseEmptyReservedCustom() const;
+ void eraseInt() const;
+ void eraseMovable() const;
+ void eraseCustom() const;
+ void eraseReservedInt() const;
+ void eraseReservedMovable() const;
+ void eraseReservedCustom() const;
+ void fillInt() const;
+ void fillMovable() const;
+ void fillCustom() const;
void first() const;
- void fromList() const;
+ void fromListInt() const;
+ void fromListMovable() const;
+ void fromListCustom() const;
void fromStdVector() const;
void indexOf() const;
void insert() const;
@@ -67,11 +224,26 @@ private slots:
void last() const;
void lastIndexOf() const;
void mid() const;
- void prepend() const;
- void remove() const;
- void size() const;
+ void prependInt() const;
+ void prependMovable() const;
+ void prependCustom() const;
+ void removeInt() const;
+ void removeMovable() const;
+ void removeCustom() const;
+ void resizePOD_data() const;
+ void resizePOD() const;
+ void resizeComplexMovable_data() const;
+ void resizeComplexMovable() const;
+ void resizeComplex_data() const;
+ void resizeComplex() const;
+ void resizeCtorAndDtor() const;
+ void sizeInt() const;
+ void sizeMovable() const;
+ void sizeCustom() const;
void startsWith() const;
- void swap() const;
+ void swapInt() const;
+ void swapMovable() const;
+ void swapCustom() const;
void toList() const;
void toStdVector() const;
void value() const;
@@ -82,44 +254,272 @@ private slots:
void reserve();
void reallocAfterCopy_data();
void reallocAfterCopy();
- void initializeList();
+ void initializeListInt();
+ void initializeListMovable();
+ void initializeListCustom();
void const_shared_null();
- void setSharable_data();
- void setSharable();
+ void setSharableInt_data();
+ void setSharableInt();
+ void setSharableMovable_data();
+ void setSharableMovable();
+ void setSharableCustom_data();
+ void setSharableCustom();
+
+ void detachInt() const;
+ void detachMovable() const;
+ void detachCustom() const;
+private:
+ template<typename T> void copyConstructor() const;
+ template<typename T> void add() const;
+ template<typename T> void append() const;
+ template<typename T> void capacity() const;
+ template<typename T> void clear() const;
+ template<typename T> void count() const;
+ template<typename T> void empty() const;
+ template<typename T> void eraseEmpty() const;
+ template<typename T> void eraseEmptyReserved() const;
+ template<typename T> void erase() const;
+ template<typename T> void eraseReserved() const;
+ template<typename T> void fill() const;
+ template<typename T> void fromList() const;
+ template<typename T> void prepend() const;
+ template<typename T> void remove() const;
+ template<typename T> void size() const;
+ template<typename T> void swap() const;
+ template<typename T> void initializeList();
+ template<typename T> void setSharable_data() const;
+ template<typename T> void setSharable() const;
+ template<typename T> void detach() const;
};
-void tst_QVector::constructors() const
+template<typename T> struct SimpleValue
{
- // pre-reserve capacity
+ static T at(int index)
{
- QVector<int> myvec(5);
-
- QVERIFY(myvec.capacity() == 5);
+ return Values[index % MaxIndex];
}
+ static const uint MaxIndex = 6;
+ static const T Values[MaxIndex];
+};
+template<>
+const int SimpleValue<int>::Values[] = { 110, 105, 101, 114, 111, 98 };
+template<>
+const Movable SimpleValue<Movable>::Values[] = { 110, 105, 101, 114, 111, 98 };
+template<>
+const Custom SimpleValue<Custom>::Values[] = { 110, 105, 101, 114, 111, 98 };
+
+void tst_QVector::constructors_empty() const
+{
+ QVector<int> emptyInt;
+ QVector<Movable> emptyMovable;
+ QVector<Custom> emptyCustom;
+}
+
+void tst_QVector::constructors_emptyReserveZero() const
+{
+ QVector<int> emptyInt(0);
+ QVector<Movable> emptyMovable(0);
+ QVector<Custom> emptyCustom(0);
+}
+
+void tst_QVector::constructors_emptyReserve() const
+{
+ // pre-reserve capacity
+ QVector<int> myInt(5);
+ QVERIFY(myInt.capacity() == 5);
+ QVector<Movable> myMovable(5);
+ QVERIFY(myMovable.capacity() == 5);
+ QVector<Custom> myCustom(4);
+ QVERIFY(myCustom.capacity() == 4);
+}
+
+void tst_QVector::constructors_reserveAndInitialize() const
+{
// default-initialise items
+
+ QVector<int> myInt(5, 42);
+ QVERIFY(myInt.capacity() == 5);
+ foreach (int meaningoflife, myInt) {
+ QCOMPARE(meaningoflife, 42);
+ }
+
+ QVector<QString> myString(5, QString::fromLatin1("c++"));
+ QVERIFY(myString.capacity() == 5);
+ // make sure all items are initialised ok
+ foreach (QString meaningoflife, myString) {
+ QCOMPARE(meaningoflife, QString::fromLatin1("c++"));
+ }
+
+ QVector<Custom> myCustom(5, Custom('n'));
+ QVERIFY(myCustom.capacity() == 5);
+ // make sure all items are initialised ok
+ foreach (Custom meaningoflife, myCustom) {
+ QCOMPARE(meaningoflife.i, 'n');
+ }
+}
+
+template<typename T>
+void tst_QVector::copyConstructor() const
+{
+ T value1(SimpleValue<T>::at(0));
+ T value2(SimpleValue<T>::at(1));
+ T value3(SimpleValue<T>::at(2));
+ T value4(SimpleValue<T>::at(3));
{
- QVector<int> myvec(5, 42);
+ QVector<T> v1;
+ QVector<T> v2(v1);
+ QCOMPARE(v1, v2);
+ }
+ {
+ QVector<T> v1;
+ v1.setSharable(false);
+ QVector<T> v2(v1);
+ QVERIFY(!v1.isSharedWith(v2));
+ QCOMPARE(v1, v2);
+ }
+ {
+ QVector<T> v1;
+ v1 << value1 << value2 << value3 << value4;
+ QVector<T> v2(v1);
+ QCOMPARE(v1, v2);
+ }
+ {
+ QVector<T> v1;
+ v1 << value1 << value2 << value3 << value4;
+ v1.setSharable(false);
+ QVector<T> v2(v1);
+ QVERIFY(!v1.isSharedWith(v2));
+ QCOMPARE(v1, v2);
+ }
+}
- QVERIFY(myvec.capacity() == 5);
+void tst_QVector::copyConstructorInt() const
+{
+ copyConstructor<int>();
+}
- // make sure all items are initialised ok
- foreach (int meaningoflife, myvec) {
- QCOMPARE(meaningoflife, 42);
- }
+void tst_QVector::copyConstructorMovable() const
+{
+ const int instancesCount = Movable::counter;
+ copyConstructor<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::copyConstructorCustom() const
+{
+ const int instancesCount = Custom::counter;
+ copyConstructor<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
+template<typename T>
+void tst_QVector::add() const
+{
+ {
+ QVector<T> empty1;
+ QVector<T> empty2;
+ QVERIFY((empty1 + empty2).isEmpty());
+ empty1 += empty2;
+ QVERIFY(empty1.isEmpty());
+ QVERIFY(empty2.isEmpty());
}
+ {
+ QVector<T> v(12);
+ QVector<T> empty;
+ QCOMPARE((v + empty), v);
+ v += empty;
+ QVERIFY(!v.isEmpty());
+ QCOMPARE(v.size(), 12);
+ QVERIFY(empty.isEmpty());
+ }
+ {
+ QVector<T> v1(12);
+ QVector<T> v2;
+ v2 += v1;
+ QVERIFY(!v1.isEmpty());
+ QCOMPARE(v1.size(), 12);
+ QVERIFY(!v2.isEmpty());
+ QCOMPARE(v2.size(), 12);
+ }
+}
+
+void tst_QVector::addInt() const
+{
+ add<int>();
+}
+
+void tst_QVector::addMovable() const
+{
+ const int instancesCount = Movable::counter;
+ add<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
}
+void tst_QVector::addCustom() const
+{
+ const int instancesCount = Custom::counter;
+ add<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
+template<typename T>
void tst_QVector::append() const
{
- QVector<int> myvec;
- myvec.append(42);
- myvec.append(43);
- myvec.append(44);
+ {
+ QVector<T> myvec;
+ myvec.append(SimpleValue<T>::at(0));
+ QVERIFY(myvec.size() == 1);
+ myvec.append(SimpleValue<T>::at(1));
+ QVERIFY(myvec.size() == 2);
+ myvec.append(SimpleValue<T>::at(2));
+ QVERIFY(myvec.size() == 3);
- QVERIFY(myvec.size() == 3);
- QCOMPARE(myvec, QVector<int>() << 42 << 43 << 44);
+ QCOMPARE(myvec, QVector<T>() << SimpleValue<T>::at(0)
+ << SimpleValue<T>::at(1)
+ << SimpleValue<T>::at(2));
+ }
+ {
+ QVector<T> v(2);
+ v.append(SimpleValue<T>::at(0));
+ QVERIFY(v.size() == 3);
+ QCOMPARE(v.at(v.size() - 1), SimpleValue<T>::at(0));
+ }
+ {
+ QVector<T> v(2);
+ v.reserve(12);
+ v.append(SimpleValue<T>::at(0));
+ QVERIFY(v.size() == 3);
+ QCOMPARE(v.at(v.size() - 1), SimpleValue<T>::at(0));
+ }
+ {
+ QVector<T> v(2);
+ v.reserve(12);
+ v.setSharable(false);
+ v.append(SimpleValue<T>::at(0));
+ QVERIFY(v.size() == 3);
+ QCOMPARE(v.last(), SimpleValue<T>::at(0));
+ }
+}
+
+void tst_QVector::appendInt() const
+{
+ append<int>();
+}
+
+void tst_QVector::appendMovable() const
+{
+ const int instancesCount = Movable::counter;
+ append<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::appendCustom() const
+{
+ const int instancesCount = Custom::counter;
+ append<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
}
void tst_QVector::at() const
@@ -148,20 +548,21 @@ void tst_QVector::at() const
QCOMPARE(myvec.at(2), QLatin1String("hello"));
}
+template<typename T>
void tst_QVector::capacity() const
{
- QVector<QString> myvec;
+ QVector<T> myvec;
// TODO: is this guaranteed? seems a safe assumption, but I suppose preallocation of a
// few items isn't an entirely unforseeable possibility.
QVERIFY(myvec.capacity() == 0);
// test it gets a size
- myvec << "aaa" << "bbb" << "ccc";
+ myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2);
QVERIFY(myvec.capacity() >= 3);
// make sure it grows ok
- myvec << "aaa" << "bbb" << "ccc";
+ myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2);
QVERIFY(myvec.capacity() >= 6);
// let's try squeeze a bit
@@ -182,10 +583,30 @@ void tst_QVector::capacity() const
QVERIFY(myvec.capacity() == 0);
}
+void tst_QVector::capacityInt() const
+{
+ capacity<int>();
+}
+
+void tst_QVector::capacityMovable() const
+{
+ const int instancesCount = Movable::counter;
+ capacity<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::capacityCustom() const
+{
+ const int instancesCount = Custom::counter;
+ capacity<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
+template<typename T>
void tst_QVector::clear() const
{
- QVector<QString> myvec;
- myvec << "aaa" << "bbb" << "ccc";
+ QVector<T> myvec;
+ myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2);
QVERIFY(myvec.size() == 3);
myvec.clear();
@@ -193,6 +614,25 @@ void tst_QVector::clear() const
QVERIFY(myvec.capacity() == 0);
}
+void tst_QVector::clearInt() const
+{
+ clear<int>();
+}
+
+void tst_QVector::clearMovable() const
+{
+ const int instancesCount = Movable::counter;
+ clear<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::clearCustom() const
+{
+ const int instancesCount = Custom::counter;
+ clear<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
void tst_QVector::constData() const
{
int arr[] = { 42, 43, 44 };
@@ -217,18 +657,19 @@ void tst_QVector::contains() const
QVERIFY(myvec.contains(QLatin1String("I don't exist")));
}
+template<typename T>
void tst_QVector::count() const
{
// total size
{
// zero size
- QVector<int> myvec;
+ QVector<T> myvec;
QVERIFY(myvec.count() == 0);
// grow
- myvec.append(42);
+ myvec.append(SimpleValue<T>::at(0));
QVERIFY(myvec.count() == 1);
- myvec.append(42);
+ myvec.append(SimpleValue<T>::at(1));
QVERIFY(myvec.count() == 2);
// shrink
@@ -240,23 +681,42 @@ void tst_QVector::count() const
// count of items
{
- QVector<QString> myvec;
- myvec << "aaa" << "bbb" << "ccc";
+ QVector<T> myvec;
+ myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2);
// initial tests
- QVERIFY(myvec.count(QLatin1String("aaa")) == 1);
- QVERIFY(myvec.count(QLatin1String("pirates")) == 0);
+ QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 1);
+ QVERIFY(myvec.count(SimpleValue<T>::at(3)) == 0);
// grow
- myvec.append(QLatin1String("aaa"));
- QVERIFY(myvec.count(QLatin1String("aaa")) == 2);
+ myvec.append(SimpleValue<T>::at(0));
+ QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 2);
// shrink
myvec.remove(0);
- QVERIFY(myvec.count(QLatin1String("aaa")) == 1);
+ QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 1);
}
}
+void tst_QVector::countInt() const
+{
+ count<int>();
+}
+
+void tst_QVector::countMovable() const
+{
+ const int instancesCount = Movable::counter;
+ count<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::countCustom() const
+{
+ const int instancesCount = Custom::counter;
+ count<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
void tst_QVector::data() const
{
QVector<int> myvec;
@@ -275,15 +735,16 @@ void tst_QVector::data() const
QVERIFY(memcmp(myvec.data(), reinterpret_cast<int *>(&arr), sizeof(int) * 3) == 0);
}
+template<typename T>
void tst_QVector::empty() const
{
- QVector<int> myvec;
+ QVector<T> myvec;
// starts empty
QVERIFY(myvec.empty());
// not empty
- myvec.append(1);
+ myvec.append(SimpleValue<T>::at(2));
QVERIFY(!myvec.empty());
// empty again
@@ -291,6 +752,25 @@ void tst_QVector::empty() const
QVERIFY(myvec.empty());
}
+void tst_QVector::emptyInt() const
+{
+ empty<int>();
+}
+
+void tst_QVector::emptyMovable() const
+{
+ const int instancesCount = Movable::counter;
+ empty<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::emptyCustom() const
+{
+ const int instancesCount = Custom::counter;
+ empty<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
void tst_QVector::endsWith() const
{
QVector<int> myvec;
@@ -311,18 +791,244 @@ void tst_QVector::endsWith() const
QVERIFY(myvec.endsWith(1));
}
+template<typename T>
+void tst_QVector::eraseEmpty() const
+{
+ {
+ QVector<T> v;
+ v.erase(v.begin());
+ QCOMPARE(v.size(), 0);
+ v.erase(v.begin(), v.end());
+ QCOMPARE(v.size(), 0);
+ }
+ {
+ QVector<T> v;
+ v.setSharable(false);
+ v.erase(v.begin());
+ QCOMPARE(v.size(), 0);
+ v.erase(v.begin(), v.end());
+ QCOMPARE(v.size(), 0);
+ }
+}
+
+void tst_QVector::eraseEmptyInt() const
+{
+ eraseEmpty<int>();
+}
+
+void tst_QVector::eraseEmptyMovable() const
+{
+ const int instancesCount = Movable::counter;
+ eraseEmpty<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::eraseEmptyCustom() const
+{
+ const int instancesCount = Custom::counter;
+ eraseEmpty<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
+template<typename T>
+void tst_QVector::eraseEmptyReserved() const
+{
+ {
+ QVector<T> v;
+ v.reserve(10);
+ v.erase(v.begin());
+ QCOMPARE(v.size(), 0);
+ v.erase(v.begin(), v.end());
+ QCOMPARE(v.size(), 0);
+ }
+ {
+ QVector<T> v;
+ v.reserve(10);
+ v.setSharable(false);
+ v.erase(v.begin());
+ QCOMPARE(v.size(), 0);
+ v.erase(v.begin(), v.end());
+ QCOMPARE(v.size(), 0);
+ }
+}
+
+void tst_QVector::eraseEmptyReservedInt() const
+{
+ eraseEmptyReserved<int>();
+}
+
+void tst_QVector::eraseEmptyReservedMovable() const
+{
+ const int instancesCount = Movable::counter;
+ eraseEmptyReserved<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::eraseEmptyReservedCustom() const
+{
+ const int instancesCount = Custom::counter;
+ eraseEmptyReserved<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
+template<typename T>
+void tst_QVector::erase() const
+{
+ {
+ QVector<T> v(12);
+ v.erase(v.begin());
+ QCOMPARE(v.size(), 11);
+ v.erase(v.begin(), v.end());
+ QCOMPARE(v.size(), 0);
+ }
+ {
+ QVector<T> v(12);
+ v.erase(v.begin() + 1);
+ QCOMPARE(v.size(), 11);
+ v.erase(v.begin() + 1, v.end());
+ QCOMPARE(v.size(), 1);
+ }
+ {
+ QVector<T> v(12);
+ v.erase(v.begin(), v.end() - 1);
+ QCOMPARE(v.size(), 1);
+ }
+ {
+ QVector<T> v(12);
+ v.erase(v.begin() + 5);
+ QCOMPARE(v.size(), 11);
+ v.erase(v.begin() + 1, v.end() - 1);
+ QCOMPARE(v.size(), 2);
+ }
+ {
+ QVector<T> v(10);
+ v.setSharable(false);
+ v.erase(v.begin() + 3);
+ QCOMPARE(v.size(), 9);
+ v.erase(v.begin(), v.end() - 1);
+ QCOMPARE(v.size(), 1);
+ }
+}
+
+void tst_QVector::eraseInt() const
+{
+ erase<int>();
+}
+
+void tst_QVector::eraseMovable() const
+{
+ const int instancesCount = Movable::counter;
+ erase<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::eraseCustom() const
+{
+ const int instancesCount = Custom::counter;
+ erase<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
+template<typename T> void tst_QVector::eraseReserved() const
+{
+ {
+ QVector<T> v(12);
+ v.reserve(16);
+ v.erase(v.begin());
+ QCOMPARE(v.size(), 11);
+ v.erase(v.begin(), v.end());
+ QCOMPARE(v.size(), 0);
+ }
+ {
+ QVector<T> v(12);
+ v.reserve(16);
+ v.erase(v.begin() + 1);
+ QCOMPARE(v.size(), 11);
+ v.erase(v.begin() + 1, v.end());
+ QCOMPARE(v.size(), 1);
+ }
+ {
+ QVector<T> v(12);
+ v.reserve(16);
+ v.erase(v.begin(), v.end() - 1);
+ QCOMPARE(v.size(), 1);
+ }
+ {
+ QVector<T> v(12);
+ v.reserve(16);
+ v.erase(v.begin() + 5);
+ QCOMPARE(v.size(), 11);
+ v.erase(v.begin() + 1, v.end() - 1);
+ QCOMPARE(v.size(), 2);
+ }
+ {
+ QVector<T> v(10);
+ v.reserve(16);
+ v.setSharable(false);
+ v.erase(v.begin() + 3);
+ QCOMPARE(v.size(), 9);
+ v.erase(v.begin(), v.end() - 1);
+ QCOMPARE(v.size(), 1);
+ }
+}
+
+void tst_QVector::eraseReservedInt() const
+{
+ eraseReserved<int>();
+}
+
+void tst_QVector::eraseReservedMovable() const
+{
+ const int instancesCount = Movable::counter;
+ eraseReserved<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::eraseReservedCustom() const
+{
+ const int instancesCount = Custom::counter;
+ eraseReserved<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
+template<typename T>
void tst_QVector::fill() const
{
- QVector<int> myvec;
+ QVector<T> myvec;
// resize
myvec.resize(5);
- myvec.fill(69);
- QCOMPARE(myvec, QVector<int>() << 69 << 69 << 69 << 69 << 69);
+ myvec.fill(SimpleValue<T>::at(1));
+ QCOMPARE(myvec, QVector<T>() << SimpleValue<T>::at(1) << SimpleValue<T>::at(1)
+ << SimpleValue<T>::at(1) << SimpleValue<T>::at(1)
+ << SimpleValue<T>::at(1));
// make sure it can resize itself too
- myvec.fill(42, 10);
- QCOMPARE(myvec, QVector<int>() << 42 << 42 << 42 << 42 << 42 << 42 << 42 << 42 << 42 << 42);
+ myvec.fill(SimpleValue<T>::at(2), 10);
+ QCOMPARE(myvec, QVector<T>() << SimpleValue<T>::at(2) << SimpleValue<T>::at(2)
+ << SimpleValue<T>::at(2) << SimpleValue<T>::at(2)
+ << SimpleValue<T>::at(2) << SimpleValue<T>::at(2)
+ << SimpleValue<T>::at(2) << SimpleValue<T>::at(2)
+ << SimpleValue<T>::at(2) << SimpleValue<T>::at(2));
+}
+
+void tst_QVector::fillInt() const
+{
+ fill<int>();
+}
+
+void tst_QVector::fillMovable() const
+{
+ const int instancesCount = Movable::counter;
+ fill<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::fillCustom() const
+{
+ const int instancesCount = Custom::counter;
+ fill<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
}
void tst_QVector::first() const
@@ -342,17 +1048,37 @@ void tst_QVector::first() const
QCOMPARE(myvec.first(), 23);
}
+template<typename T>
void tst_QVector::fromList() const
{
- QList<QString> list;
- list << "aaa" << "bbb" << "ninjas" << "pirates";
+ QList<T> list;
+ list << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3);
- QVector<QString> myvec;
- myvec = QVector<QString>::fromList(list);
+ QVector<T> myvec;
+ myvec = QVector<T>::fromList(list);
// test it worked ok
- QCOMPARE(myvec, QVector<QString>() << "aaa" << "bbb" << "ninjas" << "pirates");
- QCOMPARE(list, QList<QString>() << "aaa" << "bbb" << "ninjas" << "pirates");
+ QCOMPARE(myvec, QVector<T>() << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3));
+ QCOMPARE(list, QList<T>() << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3));
+}
+
+void tst_QVector::fromListInt() const
+{
+ fromList<int>();
+}
+
+void tst_QVector::fromListMovable() const
+{
+ const int instancesCount = Movable::counter;
+ fromList<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::fromListCustom() const
+{
+ const int instancesCount = Custom::counter;
+ fromList<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
}
void tst_QVector::fromStdVector() const
@@ -486,73 +1212,382 @@ void tst_QVector::mid() const
QCOMPARE(list.mid(4), QVector<QString>() << "buck" << "hello" << "kitty");
}
+template<typename T>
void tst_QVector::prepend() const
{
- QVector<QString> myvec;
- myvec << "A" << "B" << "C";
+ QVector<T> myvec;
+ T val1 = SimpleValue<T>::at(0);
+ T val2 = SimpleValue<T>::at(1);
+ T val3 = SimpleValue<T>::at(2);
+ T val4 = SimpleValue<T>::at(3);
+ T val5 = SimpleValue<T>::at(4);
+ myvec << val1 << val2 << val3;
// starts ok
QVERIFY(myvec.size() == 3);
- QCOMPARE(myvec.at(0), QLatin1String("A"));
+ QCOMPARE(myvec.at(0), val1);
// add something
- myvec.prepend(QLatin1String("X"));
- QCOMPARE(myvec.at(0), QLatin1String("X"));
- QCOMPARE(myvec.at(1), QLatin1String("A"));
+ myvec.prepend(val4);
+ QCOMPARE(myvec.at(0), val4);
+ QCOMPARE(myvec.at(1), val1);
QVERIFY(myvec.size() == 4);
// something else
- myvec.prepend(QLatin1String("Z"));
- QCOMPARE(myvec.at(0), QLatin1String("Z"));
- QCOMPARE(myvec.at(1), QLatin1String("X"));
- QCOMPARE(myvec.at(2), QLatin1String("A"));
+ myvec.prepend(val5);
+ QCOMPARE(myvec.at(0), val5);
+ QCOMPARE(myvec.at(1), val4);
+ QCOMPARE(myvec.at(2), val1);
QVERIFY(myvec.size() == 5);
- // clear and append to an empty vector
+ // clear and prepend to an empty vector
myvec.clear();
QVERIFY(myvec.size() == 0);
- myvec.prepend(QLatin1String("ninjas"));
+ myvec.prepend(val5);
QVERIFY(myvec.size() == 1);
- QCOMPARE(myvec.at(0), QLatin1String("ninjas"));
+ QCOMPARE(myvec.at(0), val5);
}
-void tst_QVector::remove() const
+void tst_QVector::prependInt() const
{
- QVector<QString> myvec;
- myvec << "A" << "B" << "C";
+ prepend<int>();
+}
+
+void tst_QVector::prependMovable() const
+{
+ const int instancesCount = Movable::counter;
+ prepend<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::prependCustom() const
+{
+ const int instancesCount = Custom::counter;
+ prepend<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+template<typename T>
+void tst_QVector::remove() const
+{
+ QVector<T> myvec;
+ T val1 = SimpleValue<T>::at(1);
+ T val2 = SimpleValue<T>::at(2);
+ T val3 = SimpleValue<T>::at(3);
+ myvec << val1 << val2 << val3;
// remove middle
myvec.remove(1);
- QCOMPARE(myvec, QVector<QString>() << "A" << "C");
+ QCOMPARE(myvec, QVector<T>() << val1 << val3);
// remove rest
myvec.remove(0, 2);
- QCOMPARE(myvec, QVector<QString>());
+ QCOMPARE(myvec, QVector<T>());
}
-// ::reserve() is really hard to think of tests for, so not doing it.
-// ::resize() is tested in ::capacity().
+void tst_QVector::removeInt() const
+{
+ remove<int>();
+}
-void tst_QVector::size() const
+void tst_QVector::removeMovable() const
{
- // total size
+ const int instancesCount = Movable::counter;
+ remove<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::removeCustom() const
+{
+ const int instancesCount = Custom::counter;
+ remove<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
+void tst_QVector::resizePOD_data() const
+{
+ QTest::addColumn<QVector<int> >("vector");
+ QTest::addColumn<int>("size");
+
+ QVERIFY(!QTypeInfo<int>::isComplex);
+ QVERIFY(!QTypeInfo<int>::isStatic);
+
+ QVector<int> null;
+ QVector<int> empty(0, 5);
+ QVector<int> emptyReserved;
+ QVector<int> nonEmpty;
+ QVector<int> nonEmptyReserved;
+
+ emptyReserved.reserve(10);
+ nonEmptyReserved.reserve(15);
+ nonEmpty << 0 << 1 << 2 << 3 << 4;
+ nonEmptyReserved << 0 << 1 << 2 << 3 << 4 << 5 << 6;
+ QVERIFY(emptyReserved.capacity() >= 10);
+ QVERIFY(nonEmptyReserved.capacity() >= 15);
+
+ QVector<int> nullNotShared;
+ QVector<int> emptyNotShared(0, 5);
+ QVector<int> emptyReservedNotShared;
+ QVector<int> nonEmptyNotShared;
+ QVector<int> nonEmptyReservedNotShared;
+
+ emptyReservedNotShared.reserve(10);
+ nonEmptyReservedNotShared.reserve(15);
+ nonEmptyNotShared << 0 << 1 << 2 << 3 << 4;
+ nonEmptyReservedNotShared << 0 << 1 << 2 << 3 << 4 << 5 << 6;
+ QVERIFY(emptyReservedNotShared.capacity() >= 10);
+ QVERIFY(nonEmptyReservedNotShared.capacity() >= 15);
+
+ emptyNotShared.setSharable(false);
+ emptyReservedNotShared.setSharable(false);
+ nonEmptyNotShared.setSharable(false);
+ nonEmptyReservedNotShared.setSharable(false);
+
+ QTest::newRow("null") << null << 10;
+ QTest::newRow("empty") << empty << 10;
+ QTest::newRow("emptyReserved") << emptyReserved << 10;
+ QTest::newRow("nonEmpty") << nonEmpty << 10;
+ QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10;
+ QTest::newRow("nullNotShared") << nullNotShared << 10;
+ QTest::newRow("emptyNotShared") << emptyNotShared << 10;
+ QTest::newRow("emptyReservedNotShared") << emptyReservedNotShared << 10;
+ QTest::newRow("nonEmptyNotShared") << nonEmptyNotShared << 10;
+ QTest::newRow("nonEmptyReservedNotShared") << nonEmptyReservedNotShared << 10;
+}
+
+void tst_QVector::resizePOD() const
+{
+ QFETCH(QVector<int>, vector);
+ QFETCH(int, size);
+
+ const int oldSize = vector.size();
+
+ vector.resize(size);
+ QCOMPARE(vector.size(), size);
+ QVERIFY(vector.capacity() >= size);
+ for (int i = oldSize; i < size; ++i)
+ QVERIFY(vector[i] == 0); // check initialization
+
+ const int capacity = vector.capacity();
+
+ vector.resize(0);
+ QCOMPARE(vector.size(), 0);
+ QVERIFY(vector.capacity() <= capacity);
+}
+
+void tst_QVector::resizeComplexMovable_data() const
+{
+ QTest::addColumn<QVector<Movable> >("vector");
+ QTest::addColumn<int>("size");
+
+ QVERIFY(QTypeInfo<Movable>::isComplex);
+ QVERIFY(!QTypeInfo<Movable>::isStatic);
+
+ QVector<Movable> null;
+ QVector<Movable> empty(0, 'Q');
+ QVector<Movable> emptyReserved;
+ QVector<Movable> nonEmpty;
+ QVector<Movable> nonEmptyReserved;
+
+ emptyReserved.reserve(10);
+ nonEmptyReserved.reserve(15);
+ nonEmpty << '0' << '1' << '2' << '3' << '4';
+ nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6';
+ QVERIFY(emptyReserved.capacity() >= 10);
+ QVERIFY(nonEmptyReserved.capacity() >= 15);
+
+ QVector<Movable> nullNotShared;
+ QVector<Movable> emptyNotShared(0, 'Q');
+ QVector<Movable> emptyReservedNotShared;
+ QVector<Movable> nonEmptyNotShared;
+ QVector<Movable> nonEmptyReservedNotShared;
+
+ emptyReservedNotShared.reserve(10);
+ nonEmptyReservedNotShared.reserve(15);
+ nonEmptyNotShared << '0' << '1' << '2' << '3' << '4';
+ nonEmptyReservedNotShared << '0' << '1' << '2' << '3' << '4' << '5' << '6';
+ QVERIFY(emptyReservedNotShared.capacity() >= 10);
+ QVERIFY(nonEmptyReservedNotShared.capacity() >= 15);
+
+ emptyNotShared.setSharable(false);
+ emptyReservedNotShared.setSharable(false);
+ nonEmptyNotShared.setSharable(false);
+ nonEmptyReservedNotShared.setSharable(false);
+
+ QTest::newRow("null") << null << 10;
+ QTest::newRow("empty") << empty << 10;
+ QTest::newRow("emptyReserved") << emptyReserved << 10;
+ QTest::newRow("nonEmpty") << nonEmpty << 10;
+ QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10;
+ QTest::newRow("nullNotShared") << nullNotShared << 10;
+ QTest::newRow("emptyNotShared") << emptyNotShared << 10;
+ QTest::newRow("emptyReservedNotShared") << emptyReservedNotShared << 10;
+ QTest::newRow("nonEmptyNotShared") << nonEmptyNotShared << 10;
+ QTest::newRow("nonEmptyReservedNotShared") << nonEmptyReservedNotShared << 10;
+}
+
+void tst_QVector::resizeComplexMovable() const
+{
+ const int items = Movable::counter;
{
- // zero size
- QVector<int> myvec;
- QVERIFY(myvec.size() == 0);
+ QFETCH(QVector<Movable>, vector);
+ QFETCH(int, size);
- // grow
- myvec.append(42);
- QVERIFY(myvec.size() == 1);
- myvec.append(42);
- QVERIFY(myvec.size() == 2);
+ const int oldSize = vector.size();
- // shrink
- myvec.remove(0);
- QVERIFY(myvec.size() == 1);
- myvec.remove(0);
- QVERIFY(myvec.size() == 0);
+ vector.resize(size);
+ QCOMPARE(vector.size(), size);
+ QVERIFY(vector.capacity() >= size);
+ for (int i = oldSize; i < size; ++i)
+ QVERIFY(vector[i] == 'j'); // check initialization
+
+ const int capacity = vector.capacity();
+
+ vector.resize(0);
+ QCOMPARE(vector.size(), 0);
+ QVERIFY(vector.capacity() <= capacity);
+ }
+ QCOMPARE(items, Movable::counter);
+}
+
+void tst_QVector::resizeComplex_data() const
+{
+ QTest::addColumn<QVector<Custom> >("vector");
+ QTest::addColumn<int>("size");
+
+ QVERIFY(QTypeInfo<Custom>::isComplex);
+ QVERIFY(QTypeInfo<Custom>::isStatic);
+
+ QVector<Custom> null;
+ QVector<Custom> empty(0, '0');
+ QVector<Custom> emptyReserved;
+ QVector<Custom> nonEmpty;
+ QVector<Custom> nonEmptyReserved;
+
+ emptyReserved.reserve(10);
+ nonEmptyReserved.reserve(15);
+ nonEmpty << '0' << '1' << '2' << '3' << '4';
+ nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6';
+ QVERIFY(emptyReserved.capacity() >= 10);
+ QVERIFY(nonEmptyReserved.capacity() >= 15);
+
+ QVector<Custom> nullNotShared;
+ QVector<Custom> emptyNotShared(0, '0');
+ QVector<Custom> emptyReservedNotShared;
+ QVector<Custom> nonEmptyNotShared;
+ QVector<Custom> nonEmptyReservedNotShared;
+
+ emptyReservedNotShared.reserve(10);
+ nonEmptyReservedNotShared.reserve(15);
+ nonEmptyNotShared << '0' << '1' << '2' << '3' << '4';
+ nonEmptyReservedNotShared << '0' << '1' << '2' << '3' << '4' << '5' << '6';
+ QVERIFY(emptyReservedNotShared.capacity() >= 10);
+ QVERIFY(nonEmptyReservedNotShared.capacity() >= 15);
+
+ emptyNotShared.setSharable(false);
+ emptyReservedNotShared.setSharable(false);
+ nonEmptyNotShared.setSharable(false);
+ nonEmptyReservedNotShared.setSharable(false);
+
+ QTest::newRow("null") << null << 10;
+ QTest::newRow("empty") << empty << 10;
+ QTest::newRow("emptyReserved") << emptyReserved << 10;
+ QTest::newRow("nonEmpty") << nonEmpty << 10;
+ QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10;
+ QTest::newRow("nullNotShared") << nullNotShared << 10;
+ QTest::newRow("emptyNotShared") << emptyNotShared << 10;
+ QTest::newRow("emptyReservedNotShared") << emptyReservedNotShared << 10;
+ QTest::newRow("nonEmptyNotShared") << nonEmptyNotShared << 10;
+ QTest::newRow("nonEmptyReservedNotShared") << nonEmptyReservedNotShared << 10;
+}
+
+void tst_QVector::resizeComplex() const
+{
+ const int items = Custom::counter;
+ {
+ QFETCH(QVector<Custom>, vector);
+ QFETCH(int, size);
+
+ int oldSize = vector.size();
+ vector.resize(size);
+ QCOMPARE(vector.size(), size);
+ QVERIFY(vector.capacity() >= size);
+ for (int i = oldSize; i < size; ++i)
+ QVERIFY(vector[i].i == 'j'); // check default initialization
+
+ const int capacity = vector.capacity();
+
+ vector.resize(0);
+ QCOMPARE(vector.size(), 0);
+ QVERIFY(vector.isEmpty());
+ QVERIFY(vector.capacity() <= capacity);
}
+ QCOMPARE(Custom::counter, items);
+}
+
+void tst_QVector::resizeCtorAndDtor() const
+{
+ const int items = Custom::counter;
+ {
+ QVector<Custom> null;
+ QVector<Custom> empty(0, '0');
+ QVector<Custom> emptyReserved;
+ QVector<Custom> nonEmpty;
+ QVector<Custom> nonEmptyReserved;
+
+ emptyReserved.reserve(10);
+ nonEmptyReserved.reserve(15);
+ nonEmpty << '0' << '1' << '2' << '3' << '4';
+ nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6';
+ QVERIFY(emptyReserved.capacity() >= 10);
+ QVERIFY(nonEmptyReserved.capacity() >= 15);
+
+ // start playing with vectors
+ null.resize(21);
+ nonEmpty.resize(2);
+ emptyReserved.resize(0);
+ nonEmpty.resize(0);
+ nonEmptyReserved.resize(2);
+ }
+ QCOMPARE(Custom::counter, items);
+}
+
+template<typename T>
+void tst_QVector::size() const
+{
+ // zero size
+ QVector<T> myvec;
+ QVERIFY(myvec.size() == 0);
+
+ // grow
+ myvec.append(SimpleValue<T>::at(0));
+ QVERIFY(myvec.size() == 1);
+ myvec.append(SimpleValue<T>::at(1));
+ QVERIFY(myvec.size() == 2);
+
+ // shrink
+ myvec.remove(0);
+ QVERIFY(myvec.size() == 1);
+ myvec.remove(0);
+ QVERIFY(myvec.size() == 0);
+}
+
+void tst_QVector::sizeInt() const
+{
+ size<int>();
+}
+
+void tst_QVector::sizeMovable() const
+{
+ const int instancesCount = Movable::counter;
+ size<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::sizeCustom() const
+{
+ const int instancesCount = Custom::counter;
+ size<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
}
// ::squeeze() is tested in ::capacity().
@@ -577,15 +1612,41 @@ void tst_QVector::startsWith() const
QVERIFY(myvec.startsWith(1));
}
+template<typename T>
void tst_QVector::swap() const
{
- QVector<int> v1, v2;
- v1 << 1 << 2 << 3;
- v2 << 4 << 5 << 6;
+ QVector<T> v1, v2;
+ T val1 = SimpleValue<T>::at(0);
+ T val2 = SimpleValue<T>::at(1);
+ T val3 = SimpleValue<T>::at(2);
+ T val4 = SimpleValue<T>::at(3);
+ T val5 = SimpleValue<T>::at(4);
+ T val6 = SimpleValue<T>::at(5);
+ v1 << val1 << val2 << val3;
+ v2 << val4 << val5 << val6;
v1.swap(v2);
- QCOMPARE(v1,QVector<int>() << 4 << 5 << 6);
- QCOMPARE(v2,QVector<int>() << 1 << 2 << 3);
+ QCOMPARE(v1,QVector<T>() << val4 << val5 << val6);
+ QCOMPARE(v2,QVector<T>() << val1 << val2 << val3);
+}
+
+void tst_QVector::swapInt() const
+{
+ swap<int>();
+}
+
+void tst_QVector::swapMovable() const
+{
+ const int instancesCount = Movable::counter;
+ swap<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::swapCustom() const
+{
+ const int instancesCount = Custom::counter;
+ swap<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
}
void tst_QVector::toList() const
@@ -923,20 +1984,45 @@ void tst_QVector::reallocAfterCopy()
QCOMPARE(v2.size(), result4);
}
+template<typename T>
void tst_QVector::initializeList()
{
#ifdef Q_COMPILER_INITIALIZER_LISTS
- QVector<int> v1{2,3,4};
- QCOMPARE(v1, QVector<int>() << 2 << 3 << 4);
- QCOMPARE(v1, (QVector<int>{2,3,4}));
-
- QVector<QVector<int>> v2{ v1, {1}, QVector<int>(), {2,3,4} };
- QVector<QVector<int>> v3;
- v3 << v1 << (QVector<int>() << 1) << QVector<int>() << v1;
+ T val1(SimpleValue<T>::at(1));
+ T val2(SimpleValue<T>::at(2));
+ T val3(SimpleValue<T>::at(3));
+ T val4(SimpleValue<T>::at(4));
+
+ QVector<T> v1 {val1, val2, val3};
+ QCOMPARE(v1, QVector<T>() << val1 << val2 << val3);
+ QCOMPARE(v1, (QVector<T> {val1, val2, val3}));
+
+ QVector<QVector<T>> v2{ v1, {val4}, QVector<T>(), {val1, val2, val3} };
+ QVector<QVector<T>> v3;
+ v3 << v1 << (QVector<T>() << val4) << QVector<T>() << v1;
QCOMPARE(v3, v2);
#endif
}
+void tst_QVector::initializeListInt()
+{
+ initializeList<int>();
+}
+
+void tst_QVector::initializeListMovable()
+{
+ const int instancesCount = Movable::counter;
+ initializeList<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::initializeListCustom()
+{
+ const int instancesCount = Custom::counter;
+ initializeList<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
void tst_QVector::const_shared_null()
{
QVector<int> v1;
@@ -950,24 +2036,25 @@ void tst_QVector::const_shared_null()
Q_DECLARE_METATYPE(QVector<int>);
-void tst_QVector::setSharable_data()
+template<typename T>
+void tst_QVector::setSharable_data() const
{
- QTest::addColumn<QVector<int> >("vector");
+ QTest::addColumn<QVector<T> >("vector");
QTest::addColumn<int>("size");
QTest::addColumn<int>("capacity");
QTest::addColumn<bool>("isCapacityReserved");
- QVector<int> null;
- QVector<int> empty(0, 5);
- QVector<int> emptyReserved;
- QVector<int> nonEmpty;
- QVector<int> nonEmptyReserved;
+ QVector<T> null;
+ QVector<T> empty(0, SimpleValue<T>::at(1));
+ QVector<T> emptyReserved;
+ QVector<T> nonEmpty;
+ QVector<T> nonEmptyReserved;
emptyReserved.reserve(10);
nonEmptyReserved.reserve(15);
- nonEmpty << 0 << 1 << 2 << 3 << 4;
- nonEmptyReserved << 0 << 1 << 2 << 3 << 4 << 5 << 6;
+ nonEmpty << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3) << SimpleValue<T>::at(4);
+ nonEmptyReserved << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3) << SimpleValue<T>::at(4) << SimpleValue<T>::at(5) << SimpleValue<T>::at(6);
QVERIFY(emptyReserved.capacity() >= 10);
QVERIFY(nonEmptyReserved.capacity() >= 15);
@@ -979,9 +2066,25 @@ void tst_QVector::setSharable_data()
QTest::newRow("non-empty, Reserved") << nonEmptyReserved << 7 << 15 << true;
}
-void tst_QVector::setSharable()
+void tst_QVector::setSharableInt_data()
{
- QFETCH(QVector<int>, vector);
+ setSharable_data<int>();
+}
+
+void tst_QVector::setSharableMovable_data()
+{
+ setSharable_data<Movable>();
+}
+
+void tst_QVector::setSharableCustom_data()
+{
+ setSharable_data<Custom>();
+}
+
+template<typename T>
+void tst_QVector::setSharable() const
+{
+ QFETCH(QVector<T>, vector);
QFETCH(int, size);
QFETCH(int, capacity);
QFETCH(bool, isCapacityReserved);
@@ -998,19 +2101,19 @@ void tst_QVector::setSharable()
.arg(capacity)));
{
- QVector<int> copy(vector);
+ QVector<T> copy(vector);
QVERIFY(!copy.isDetached());
QVERIFY(copy.isSharedWith(vector));
}
vector.setSharable(false);
- QVERIFY(vector.isDetached() || vector.isSharedWith(QVector<int>()));
+ QVERIFY(vector.isDetached() || vector.isSharedWith(QVector<T>()));
{
- QVector<int> copy(vector);
+ QVector<T> copy(vector);
- QVERIFY(copy.isDetached() || copy.isSharedWith(QVector<int>()));
+ QVERIFY(copy.isDetached() || copy.isEmpty() || copy.isSharedWith(QVector<T>()));
QCOMPARE(copy.size(), size);
if (isCapacityReserved)
QVERIFY2(copy.capacity() >= capacity,
@@ -1023,14 +2126,14 @@ void tst_QVector::setSharable()
vector.setSharable(true);
{
- QVector<int> copy(vector);
+ QVector<T> copy(vector);
QVERIFY(!copy.isDetached());
QVERIFY(copy.isSharedWith(vector));
}
for (int i = 0; i < vector.size(); ++i)
- QCOMPARE(vector[i], i);
+ QCOMPARE(vector[i], SimpleValue<T>::at(i));
QCOMPARE(vector.size(), size);
if (isCapacityReserved)
@@ -1040,5 +2143,140 @@ void tst_QVector::setSharable()
.arg(capacity)));
}
+void tst_QVector::setSharableInt()
+{
+ setSharable<int>();
+}
+
+void tst_QVector::setSharableMovable()
+{
+ const int instancesCount = Movable::counter;
+ setSharable<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::setSharableCustom()
+{
+ const int instancesCount = Custom::counter;
+ setSharable<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
+template<typename T>
+void tst_QVector::detach() const
+{
+ {
+ // detach an empty vector
+ QVector<T> v;
+ v.detach();
+ QVERIFY(v.isDetached());
+ QCOMPARE(v.size(), 0);
+ QCOMPARE(v.capacity(), 0);
+ }
+ {
+ // detach an empty referenced vector
+ QVector<T> v;
+ QVector<T> ref(v);
+ QVERIFY(!v.isDetached());
+ v.detach();
+ QVERIFY(v.isDetached());
+ QCOMPARE(v.size(), 0);
+ QCOMPARE(v.capacity(), 0);
+ }
+ {
+ // detach a not empty referenced vector
+ QVector<T> v(31);
+ QVector<T> ref(v);
+ QVERIFY(!v.isDetached());
+ v.detach();
+ QVERIFY(v.isDetached());
+ QCOMPARE(v.size(), 31);
+ QCOMPARE(v.capacity(), 31);
+ }
+ {
+ // detach a not empty vector
+ QVector<T> v(31);
+ QVERIFY(v.isDetached());
+ v.detach(); // detaching a detached vector
+ QVERIFY(v.isDetached());
+ QCOMPARE(v.size(), 31);
+ QCOMPARE(v.capacity(), 31);
+ }
+ {
+ // detach a not empty vector with preallocated space
+ QVector<T> v(3);
+ v.reserve(8);
+ QVector<T> ref(v);
+ QVERIFY(!v.isDetached());
+ v.detach();
+ QVERIFY(v.isDetached());
+ QCOMPARE(v.size(), 3);
+ QCOMPARE(v.capacity(), 8);
+ }
+ {
+ // detach a not empty vector with preallocated space
+ QVector<T> v(3);
+ v.reserve(8);
+ QVERIFY(v.isDetached());
+ v.detach(); // detaching a detached vector
+ QVERIFY(v.isDetached());
+ QCOMPARE(v.size(), 3);
+ QCOMPARE(v.capacity(), 8);
+ }
+ {
+ // detach a not empty, initialized vector
+ QVector<T> v(7, SimpleValue<T>::at(1));
+ QVector<T> ref(v);
+ QVERIFY(!v.isDetached());
+ v.detach();
+ QVERIFY(v.isDetached());
+ QCOMPARE(v.size(), 7);
+ for (int i = 0; i < v.size(); ++i)
+ QCOMPARE(v[i], SimpleValue<T>::at(1));
+ }
+ {
+ // detach a not empty, initialized vector
+ QVector<T> v(7, SimpleValue<T>::at(2));
+ QVERIFY(v.isDetached());
+ v.detach(); // detaching a detached vector
+ QVERIFY(v.isDetached());
+ QCOMPARE(v.size(), 7);
+ for (int i = 0; i < v.size(); ++i)
+ QCOMPARE(v[i], SimpleValue<T>::at(2));
+ }
+ {
+ // detach a not empty, initialized vector with preallocated space
+ QVector<T> v(7, SimpleValue<T>::at(3));
+ v.reserve(31);
+ QVector<T> ref(v);
+ QVERIFY(!v.isDetached());
+ v.detach();
+ QVERIFY(v.isDetached());
+ QCOMPARE(v.size(), 7);
+ QCOMPARE(v.capacity(), 31);
+ for (int i = 0; i < v.size(); ++i)
+ QCOMPARE(v[i], SimpleValue<T>::at(3));
+ }
+}
+
+void tst_QVector::detachInt() const
+{
+ detach<int>();
+}
+
+void tst_QVector::detachMovable() const
+{
+ const int instancesCount = Movable::counter;
+ detach<Movable>();
+ QCOMPARE(instancesCount, Movable::counter);
+}
+
+void tst_QVector::detachCustom() const
+{
+ const int instancesCount = Custom::counter;
+ detach<Custom>();
+ QCOMPARE(instancesCount, Custom::counter);
+}
+
QTEST_APPLESS_MAIN(tst_QVector)
#include "tst_qvector.moc"
diff --git a/tests/benchmarks/corelib/tools/qvector/outofline.cpp b/tests/benchmarks/corelib/tools/qvector/outofline.cpp
index bf929780a5..138812833f 100644
--- a/tests/benchmarks/corelib/tools/qvector/outofline.cpp
+++ b/tests/benchmarks/corelib/tools/qvector/outofline.cpp
@@ -79,3 +79,36 @@ std::vector<double> stdvector_fill_and_return_helper()
return v;
}
+const QVectorData QVectorData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, 0 };
+
+static inline int alignmentThreshold()
+{
+ // malloc on 32-bit platforms should return pointers that are 8-byte aligned or more
+ // while on 64-bit platforms they should be 16-byte aligned or more
+ return 2 * sizeof(void*);
+}
+
+QVectorData *QVectorData::allocate(int size, int alignment)
+{
+ return static_cast<QVectorData *>(alignment > alignmentThreshold() ? qMallocAligned(size, alignment) : ::malloc(size));
+}
+
+QVectorData *QVectorData::reallocate(QVectorData *x, int newsize, int oldsize, int alignment)
+{
+ if (alignment > alignmentThreshold())
+ return static_cast<QVectorData *>(qReallocAligned(x, newsize, oldsize, alignment));
+ return static_cast<QVectorData *>(realloc(x, newsize));
+}
+
+void QVectorData::free(QVectorData *x, int alignment)
+{
+ if (alignment > alignmentThreshold())
+ qFreeAligned(x);
+ else
+ ::free(x);
+}
+
+int QVectorData::grow(int sizeOfHeader, int size, int sizeOfT)
+{
+ return qAllocMore(size * sizeOfT, sizeOfHeader) / sizeOfT;
+}
diff --git a/tests/benchmarks/corelib/tools/qvector/qrawvector.h b/tests/benchmarks/corelib/tools/qvector/qrawvector.h
index 18d9847c95..7d80c125ea 100644
--- a/tests/benchmarks/corelib/tools/qvector/qrawvector.h
+++ b/tests/benchmarks/corelib/tools/qvector/qrawvector.h
@@ -47,6 +47,7 @@
#include <QtCore/qatomic.h>
#include <QtCore/qalgorithms.h>
#include <QtCore/qlist.h>
+#include <QtCore/private/qtools_p.h>
#include <iterator>
#include <vector>
@@ -59,7 +60,32 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
+struct QVectorData
+{
+ QtPrivate::RefCount ref;
+ int size;
+ uint alloc : 31;
+ uint capacityReserved : 1;
+
+ qptrdiff offset;
+
+ void* data() { return reinterpret_cast<char *>(this) + this->offset; }
+
+ static const QVectorData shared_null;
+ static QVectorData *allocate(int size, int alignment);
+ static QVectorData *reallocate(QVectorData *old, int newsize, int oldsize, int alignment);
+ static void free(QVectorData *data, int alignment);
+ static int grow(int sizeOfHeader, int size, int sizeOfT);
+};
+template <typename T>
+struct QVectorTypedData : QVectorData
+{
+ T* begin() { return reinterpret_cast<T *>(this->data()); }
+ T* end() { return begin() + this->size; }
+
+ static QVectorTypedData *sharedNull() { return static_cast<QVectorTypedData *>(const_cast<QVectorData *>(&QVectorData::shared_null)); }
+};
template <typename T>
class QRawVector
diff --git a/tests/benchmarks/corelib/tools/qvector/qvector.pro b/tests/benchmarks/corelib/tools/qvector/qvector.pro
index e24b16230a..24a65d8ee8 100644
--- a/tests/benchmarks/corelib/tools/qvector/qvector.pro
+++ b/tests/benchmarks/corelib/tools/qvector/qvector.pro
@@ -1,5 +1,5 @@
TARGET = tst_bench_vector
-QT = core testlib
+QT = core testlib core-private
INCLUDEPATH += .
SOURCES += main.cpp outofline.cpp
CONFIG += release