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>
bb10
Marc Mutz 2014-10-16 20:52:44 +02:00
parent 350c60b79e
commit d7fa2d060a
2 changed files with 39 additions and 16 deletions

View File

@ -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.
@ -3870,28 +3877,38 @@ QAssociativeIterable::const_iterator QAssociativeIterable::end() const
return it;
}
/*!
\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))
const const_iterator it = find(*this, key);
if (it == end())
return QVariant();
if (!key_.convert(m_impl._metaType_id_key))
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;
}
/*!

View File

@ -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;