Adding detach to QArrayDataPointer
authorJoão Abecasis <joao.abecasis@nokia.com>
Thu, 24 Nov 2011 16:22:37 +0000 (17:22 +0100)
committerQt by Nokia <qt-info@nokia.com>
Fri, 6 Jan 2012 13:25:42 +0000 (14:25 +0100)
Detaching operations added to SimpleVector

Change-Id: I5f549582cf579569f08cb8d53a6d12fe32b862e6
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
src/corelib/tools/qarraydatapointer.h
tests/auto/corelib/tools/qarraydata/simplevector.h
tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp

index 0d072a5..f1cd1dc 100644 (file)
@@ -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;
 };
 
index c5e19f3..9ab28a9 100644 (file)
@@ -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;
 };
index 63a26ed..e9a3218 100644 (file)
@@ -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);
     }
 
     {