summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2014-10-16 20:52:44 +0200
committerMarc Mutz <marc.mutz@kdab.com>2015-01-04 02:20:32 +0100
commitd7fa2d060a58b0e79d7df84a4fc54f44de9b2610 (patch)
treebeb39243c6e63cc495d0d67e0f1e82c03f33e46c /src/corelib/kernel
parent350c60b79e720d005a1a554fd177dbda607079cf (diff)
Fix a memleak in QAssociativeIterable::value()
QtMetaTypePrivate::QAssociativeIterableImpl::{find,begin,end}() allocate a new _iterator, so when they're used outside of the ref-counted world of QAssociativeIterable::const_iterator, their lifetime needs to be manually managed. Instead of going to that length, which failed in previous iterations of this patch, implement value() in terms of (new) find() and let find() operate on const_iterator. Because of forwards compatibility between patch releases, use (unexported) friend functions for now with the intention to make them proper member functions come Qt 5.5. Task-number: QTBUG-41469 Change-Id: I43b21eae0c2fc4c182369e669a8b3b457be68885 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qvariant.cpp49
-rw-r--r--src/corelib/kernel/qvariant.h6
2 files changed, 39 insertions, 16 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 2ac1bb11fb..f76201802b 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -3844,6 +3844,13 @@ void QAssociativeIterable::const_iterator::end()
m_impl.end();
}
+void find(QAssociativeIterable::const_iterator &it, const QVariant &key)
+{
+ Q_ASSERT(key.userType() == it.m_impl._metaType_id_key);
+ const QtMetaTypePrivate::VariantData dkey(key.userType(), key.constData(), 0 /*key.flags()*/);
+ it.m_impl.find(dkey);
+}
+
/*!
Returns a QAssociativeIterable::const_iterator for the beginning of the container. This
can be used in stl-style iteration.
@@ -3871,27 +3878,37 @@ QAssociativeIterable::const_iterator QAssociativeIterable::end() const
}
/*!
+ \internal
+
+ Returns a QAssociativeIterable::const_iterator for the given key \a key
+ in the container, if the types are convertible.
+
+ If the key is not found, returns end().
+
+ This can be used in stl-style iteration.
+
+ \sa begin(), end(), value()
+*/
+QAssociativeIterable::const_iterator find(const QAssociativeIterable &iterable, const QVariant &key)
+{
+ QAssociativeIterable::const_iterator it(iterable, new QAtomicInt(0));
+ QVariant key_ = key;
+ if (key_.canConvert(iterable.m_impl._metaType_id_key) && key_.convert(iterable.m_impl._metaType_id_key))
+ find(it, key_);
+ else
+ it.end();
+ return it;
+}
+
+/*!
Returns the value for the given \a key in the container, if the types are convertible.
*/
QVariant QAssociativeIterable::value(const QVariant &key) const
{
- QVariant key_ = key;
- if (!key_.canConvert(m_impl._metaType_id_key))
- return QVariant();
- if (!key_.convert(m_impl._metaType_id_key))
+ const const_iterator it = find(*this, key);
+ if (it == end())
return QVariant();
- const QtMetaTypePrivate::VariantData dkey(key_.userType(), key_.constData(), 0 /*key.flags()*/);
- QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl;
- impl.find(dkey);
- QtMetaTypePrivate::QAssociativeIterableImpl endIt = m_impl;
- endIt.end();
- if (impl.equal(endIt))
- return QVariant();
- const QtMetaTypePrivate::VariantData d = impl.getCurrentValue();
- QVariant v(d.metaTypeId, d.data, d.flags);
- if (d.metaTypeId == qMetaTypeId<QVariant>())
- return *reinterpret_cast<const QVariant*>(d.data);
- return v;
+ return *it;
}
/*!
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 7dce813bb5..90f3e8fbae 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -633,6 +633,9 @@ public:
void begin();
void end();
+ // ### Qt 5.5: make find() (1st one) a member function
+ friend void find(const_iterator &it, const QVariant &key);
+ friend const_iterator find(const QAssociativeIterable &iterable, const QVariant &key);
public:
~const_iterator();
const_iterator(const const_iterator &other);
@@ -662,6 +665,9 @@ public:
const_iterator begin() const;
const_iterator end() const;
+private: // ### Qt 5.5: make it a public find() member function:
+ friend const_iterator find(const QAssociativeIterable &iterable, const QVariant &key);
+public:
QVariant value(const QVariant &key) const;