QMap - fix erase with iterator when the map is shared

Before a call to erase on a shared instance would imply that the
item was removed from the shared data (i.e all instances)

This patch improves the behavior to detach and erase the item
specified by the iterator (i.e same behavior as QVector)

Change-Id: Ia44db84fc1388d92308bf0d2b32539ac4d53850b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Thorbjørn Martsum 2013-06-16 21:43:44 +02:00 committed by The Qt Project
parent 93ffb81df6
commit a5c7a9032e
2 changed files with 78 additions and 0 deletions

View File

@ -913,6 +913,27 @@ Q_OUTOFLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::erase(iterato
Q_ASSERT_X(isValidIterator(const_iterator(it)), "QMap::erase", "The specified iterator argument 'it' is invalid");
if (d->ref.isShared()) {
const_iterator oldBegin = constBegin();
const_iterator old = const_iterator(it);
int backStepsWithSameKey = 0;
while (old != oldBegin) {
--old;
if (qMapLessThanKey(old.key(), it.key()))
break;
++backStepsWithSameKey;
}
it = find(old.key()); // ensures detach
Q_ASSERT_X(it != iterator(d->end()), "QMap::erase", "Unable to locate same key in erase after detach.");
while (backStepsWithSameKey > 0) {
++it;
--backStepsWithSameKey;
}
}
Node *n = it.i;
++it;
d->deleteNode(n);

View File

@ -87,6 +87,7 @@ private slots:
void initializerList();
void testInsertWithHint();
void testInsertMultiWithHint();
void eraseValidIteratorOnSharedMap();
};
typedef QMap<QString, QString> StringMap;
@ -1289,6 +1290,62 @@ void tst_QMap::testInsertMultiWithHint()
QCOMPARE(map.size(), 14);
}
void tst_QMap::eraseValidIteratorOnSharedMap()
{
QMap<int, int> a, b;
a.insert(10, 10);
a.insertMulti(10, 40);
a.insertMulti(10, 25);
a.insertMulti(10, 30);
a.insert(20, 20);
QMap<int, int>::iterator i = a.begin();
while (i.value() != 25)
++i;
b = a;
a.erase(i);
QCOMPARE(b.size(), 5);
QCOMPARE(a.size(), 4);
for (i = a.begin(); i != a.end(); ++i)
QVERIFY(i.value() != 25);
int itemsWith10 = 0;
for (i = b.begin(); i != b.end(); ++i)
itemsWith10 += (i.key() == 10);
QCOMPARE(itemsWith10, 4);
// Border cases
QMap <QString, QString> ms1, ms2, ms3;
ms1.insert("foo", "bar");
ms1.insertMulti("foo", "quux");
ms1.insertMulti("foo", "bar");
QMap <QString, QString>::iterator si = ms1.begin();
ms2 = ms1;
ms1.erase(si);
si = ms1.begin();
QCOMPARE(si.value(), QString("quux"));
++si;
QCOMPARE(si.value(), QString("bar"));
si = ms2.begin();
++si;
++si;
ms3 = ms2;
ms2.erase(si);
si = ms2.begin();
QCOMPARE(si.value(), QString("bar"));
++si;
QCOMPARE(si.value(), QString("quux"));
QCOMPARE(ms1.size(), 2);
QCOMPARE(ms2.size(), 2);
QCOMPARE(ms3.size(), 3);
}
QTEST_APPLESS_MAIN(tst_QMap)
#include "tst_qmap.moc"