From 7b34da9ef12554025bb4a8f4750e5807cc37f38c Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 3 Dec 2018 11:16:18 +0100 Subject: [PATCH] Add QHash::insert(const QHash &other) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As opposed to unite(), this inserts one hash into the other without duplicating elements. Change-Id: Ifc786c48f5dc3ab18c29782e73eac3c1a3ef8981 Reviewed-by: Anton Kudryavtsev Reviewed-by: MÃ¥rten Nordheim Reviewed-by: Lars Knoll --- src/corelib/tools/qhash.cpp | 12 ++++ src/corelib/tools/qhash.h | 26 +++++++ tests/auto/corelib/tools/qhash/tst_qhash.cpp | 73 ++++++++++++++++++++ 3 files changed, 111 insertions(+) diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index a53d6db997..dcac91778f 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -1807,6 +1807,18 @@ uint qHash(long double key, uint seed) noexcept \sa insertMulti() */ +/*! \fn template void QHash::insert(const QHash &other) + \since 5.15 + + Inserts all the items in the \a other hash into this hash. + + If a key is common to both hashes, its value will be replaced with the + value stored in \a other. + + \note If \a other contains multiple entries with the same key then the + final value of the key is undefined. +*/ + /*! \fn template QHash::iterator QHash::insertMulti(const Key &key, const T &value) Inserts a new item with the \a key and a value of \a value. diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 42f8dbd155..89697b1fd1 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -526,6 +526,7 @@ public: const_iterator find(const Key &key) const; const_iterator constFind(const Key &key) const; iterator insert(const Key &key, const T &value); + void insert(const QHash &hash); iterator insertMulti(const Key &key, const T &value); QHash &unite(const QHash &other); @@ -840,6 +841,31 @@ Q_INLINE_TEMPLATE typename QHash::iterator QHash::insert(const K return iterator(*node); } +template +Q_INLINE_TEMPLATE void QHash::insert(const QHash &hash) +{ + if (d == hash.d) + return; + + detach(); + + QHashData::Node *i = hash.d->firstNode(); + QHashData::Node *end = reinterpret_cast(hash.e); + while (i != end) { + Node *n = concrete(i); + Node **node = findNode(n->key, n->h); + if (*node == e) { + if (d->willGrow()) + node = findNode(n->key, n->h); + createNode(n->h, n->key, n->value, node); + } else { + if (!std::is_same::value) + (*node)->value = n->value; + } + i = QHashData::nextNode(i); + } +} + template Q_INLINE_TEMPLATE typename QHash::iterator QHash::insertMulti(const Key &akey, const T &avalue) diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp index f0aaad98bd..b98ac38288 100644 --- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp +++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp @@ -69,6 +69,7 @@ private slots: void initializerList(); void eraseValidIteratorOnSharedHash(); void equal_range(); + void insert_hash(); }; struct IdentityTracker { @@ -1643,5 +1644,77 @@ void tst_QHash::equal_range() } } +void tst_QHash::insert_hash() +{ + { + QHash hash; + hash.insert(1, 1); + hash.insert(2, 2); + hash.insert(0, -1); + + QHash hash2; + hash2.insert(0, 0); + hash2.insert(3, 3); + hash2.insert(4, 4); + + hash.insert(hash2); + + QCOMPARE(hash.count(), 5); + for (int i = 0; i < 5; ++i) + QCOMPARE(hash[i], i); + } + { + QHash hash; + hash.insert(0, 5); + + QHash hash2; + + hash.insert(hash2); + + QCOMPARE(hash.count(), 1); + QCOMPARE(hash[0], 5); + } + { + QHash hash; + QHash hash2; + hash2.insert(0, 5); + + hash.insert(hash2); + + QCOMPARE(hash.count(), 1); + QCOMPARE(hash[0], 5); + QCOMPARE(hash, hash2); + } + { + QHash hash; + hash.insert(0, 7); + hash.insert(2, 5); + hash.insert(7, 55); + + // insert into ourself, nothing should happen + hash.insert(hash); + + QCOMPARE(hash.count(), 3); + QCOMPARE(hash[0], 7); + QCOMPARE(hash[2], 5); + QCOMPARE(hash[7], 55); + } + { + // This will use a QMultiHash and then insert that into QHash, + // the ordering is undefined so we won't test that but make + // sure this isn't adding multiple entries with the same key + // to the QHash. + QHash hash; + QMultiHash hash2; + hash2.insert(0, 5); + hash2.insert(0, 6); + hash2.insert(0, 7); + + hash.insert(hash2); + + QCOMPARE(hash.count(), 1); + } +} + QTEST_APPLESS_MAIN(tst_QHash) #include "tst_qhash.moc"