summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qarraydatapointer.h24
-rw-r--r--tests/auto/corelib/tools/qarraydata/simplevector.h25
-rw-r--r--tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp37
3 files changed, 80 insertions, 6 deletions
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h
index 0d072a510e..f1cd1dc4b1 100644
--- a/src/corelib/tools/qarraydatapointer.h
+++ b/src/corelib/tools/qarraydatapointer.h
@@ -121,7 +121,31 @@ public:
d = Data::sharedEmpty();
}
+ bool detach()
+ {
+ if (d->ref.isShared()) {
+ Data *copy = clone();
+ QArrayDataPointer old(d);
+ d = copy;
+ return true;
+ }
+
+ return false;
+ }
+
private:
+ Data *clone() const Q_REQUIRED_RESULT
+ {
+ QArrayDataPointer copy(Data::allocate(d->alloc ? d->alloc : d->size,
+ d->capacityReserved));
+ if (d->size)
+ copy->copyAppend(d->begin(), d->end());
+
+ Data *result = copy.d;
+ copy.d = Data::sharedNull();
+ return result;
+ }
+
Data *d;
};
diff --git a/tests/auto/corelib/tools/qarraydata/simplevector.h b/tests/auto/corelib/tools/qarraydata/simplevector.h
index c5e19f3c55..9ab28a9ddd 100644
--- a/tests/auto/corelib/tools/qarraydata/simplevector.h
+++ b/tests/auto/corelib/tools/qarraydata/simplevector.h
@@ -93,15 +93,35 @@ public:
size_t size() const { return d->size; }
size_t capacity() const { return d->alloc; }
+ iterator begin() { detach(); return d->begin(); }
+ iterator end() { detach(); return d->end(); }
+
const_iterator begin() const { return d->begin(); }
const_iterator end() const { return d->end(); }
const_iterator constBegin() const { return begin(); }
const_iterator constEnd() const { return end(); }
+ T &operator[](size_t i) { Q_ASSERT(i < size_t(d->size)); detach(); return begin()[i]; }
+ T &at(size_t i) { Q_ASSERT(i < size_t(d->size)); detach(); return begin()[i]; }
+
const T &operator[](size_t i) const { Q_ASSERT(i < size_t(d->size)); return begin()[i]; }
const T &at(size_t i) const { Q_ASSERT(i < size_t(d->size)); return begin()[i]; }
+ T &front()
+ {
+ Q_ASSERT(!isEmpty());
+ detach();
+ return *begin();
+ }
+
+ T &back()
+ {
+ Q_ASSERT(!isEmpty());
+ detach();
+ return *(end() - 1);
+ }
+
const T &front() const
{
Q_ASSERT(!isEmpty());
@@ -231,6 +251,11 @@ public:
d.clear();
}
+ void detach()
+ {
+ d.detach();
+ }
+
private:
QArrayDataPointer<T> d;
};
diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
index 63a26ed926..e9a3218331 100644
--- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
+++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
@@ -81,6 +81,8 @@ private slots:
void arrayOps();
};
+template <class T> const T &const_(const T &t) { return t; }
+
void tst_QArrayData::referenceCounting()
{
{
@@ -320,13 +322,36 @@ void tst_QArrayData::simpleVector()
QVERIFY(v6 >= v1);
QVERIFY(!(v1 >= v6));
- QCOMPARE(v6.front(), 0);
- QCOMPARE(v6.back(), 6);
+ {
+ SimpleVector<int> temp(v6);
+
+ QCOMPARE(const_(v6).front(), 0);
+ QCOMPARE(const_(v6).back(), 6);
+
+ QVERIFY(temp.isShared());
+ QVERIFY(temp.isSharedWith(v6));
+
+ QCOMPARE(temp.front(), 0);
+ QCOMPARE(temp.back(), 6);
+
+ // Detached
+ QVERIFY(!temp.isShared());
+ const int *const tempBegin = temp.begin();
+
+ for (size_t i = 0; i < v6.size(); ++i) {
+ QCOMPARE(const_(v6)[i], int(i));
+ QCOMPARE(const_(v6).at(i), int(i));
+ QCOMPARE(&const_(v6)[i], &const_(v6).at(i));
+
+ QCOMPARE(const_(v8)[i], const_(v6)[i]);
+
+ QCOMPARE(temp[i], int(i));
+ QCOMPARE(temp.at(i), int(i));
+ QCOMPARE(&temp[i], &temp.at(i));
+ }
- for (size_t i = 0; i < v6.size(); ++i) {
- QCOMPARE(v6[i], int(i));
- QCOMPARE(v6.at(i), int(i));
- QCOMPARE(&v6[i], &v6.at(i));
+ // A single detach should do
+ QCOMPARE(temp.begin(), tempBegin);
}
{