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
parent
93ffb81df6
commit
a5c7a9032e
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue