diff options
author | Stephen Kelly <stephen.kelly@kdab.com> | 2013-04-05 13:23:38 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-05-20 09:09:06 +0200 |
commit | 87e27eb870d08ee8953cc9b350ed29c5b3e4f785 (patch) | |
tree | 8e022660f5fb09e617707b9d0c6eeb321f66df5c /src/corelib/kernel/qvariant.h | |
parent | 65f953407a3a1726db3949743c28e1f9e2ad0e8b (diff) |
Add container access functionality for associative containers in QVariant.
Change-Id: I4763a4c157e52918a0a68cba63624c0649aca235
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
Diffstat (limited to 'src/corelib/kernel/qvariant.h')
-rw-r--r-- | src/corelib/kernel/qvariant.h | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 5588cdb27c..271aaf13ce 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -632,6 +632,103 @@ public: { return m_impl._iteratorCapabilities & QtMetaTypePrivate::BiDirectionalCapability; } }; +class QAssociativeIterable +{ + QtMetaTypePrivate::QAssociativeIterableImpl m_impl; +public: + struct const_iterator + { + private: + QtMetaTypePrivate::QAssociativeIterableImpl m_impl; + QAtomicInt *ref; + friend class QAssociativeIterable; + inline explicit const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_) + : m_impl(iter.m_impl), ref(ref_) { ref->ref(); } + + inline explicit const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_) + : m_impl(impl), ref(ref_) { ref->ref(); } + + inline void begin() { m_impl.begin(); } + inline void end() { m_impl.end(); } + public: + inline ~const_iterator() { + if (!ref->deref()) { + m_impl.destroyIter(); + } + } + inline const_iterator(const const_iterator &other) : m_impl(other.m_impl), ref(other.ref) { + ref->ref(); + } + + inline const QVariant key() const { + const QtMetaTypePrivate::VariantData d = m_impl.getCurrentKey(); + QVariant v(d.metaTypeId, d.data, d.flags); + if (d.metaTypeId == qMetaTypeId<QVariant>()) + return *reinterpret_cast<const QVariant*>(d.data); + return v; + } + + inline const QVariant value() const { + const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue(); + QVariant v(d.metaTypeId, d.data, d.flags); + if (d.metaTypeId == qMetaTypeId<QVariant>()) + return *reinterpret_cast<const QVariant*>(d.data); + return v; + } + + inline const QVariant operator*() const { + const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue(); + QVariant v(d.metaTypeId, d.data, d.flags); + if (d.metaTypeId == qMetaTypeId<QVariant>()) + return *reinterpret_cast<const QVariant*>(d.data); + return v; + } + inline bool operator==(const const_iterator &o) const { return m_impl.equal(o.m_impl); } + inline bool operator!=(const const_iterator &o) const { return !m_impl.equal(o.m_impl); } + inline const_iterator &operator++() { m_impl.advance(1); return *this; } + inline const_iterator operator++(int) { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; m_impl.advance(1); return const_iterator(impl, this->ref); } + inline const_iterator &operator--() { m_impl.advance(-1); return *this; } + inline const_iterator operator--(int) { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; m_impl.advance(-1); return const_iterator(impl, this->ref); } + inline const_iterator &operator+=(int j) { m_impl.advance(j); return *this; } + inline const_iterator &operator-=(int j) { m_impl.advance(-j); return *this; } + inline const_iterator operator+(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; impl.advance(j); return const_iterator(impl, this->ref); } + inline const_iterator operator-(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; impl.advance(-j); return const_iterator(impl, this->ref); } + }; + + friend struct const_iterator; + + explicit QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl impl) + : m_impl(impl) + { + } + + const_iterator begin() const { const_iterator it(*this, new QAtomicInt(0)); it.begin(); return it; } + const_iterator end() const { const_iterator it(*this, new QAtomicInt(0)); it.end(); return it; } + + QVariant 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)) + 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; + } + + int size() const { return m_impl.size(); } +}; + #ifndef QT_MOC namespace QtPrivate { template<typename T> @@ -675,6 +772,20 @@ namespace QtPrivate { } }; template<> + struct QVariantValueHelperInterface<QAssociativeIterable> + { + static QAssociativeIterable invoke(const QVariant &v) + { + if (v.userType() == qMetaTypeId<QVariantMap>()) { + return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantMap*>(v.constData()))); + } + if (v.userType() == qMetaTypeId<QVariantHash>()) { + return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantHash*>(v.constData()))); + } + return QAssociativeIterable(v.value<QtMetaTypePrivate::QAssociativeIterableImpl>()); + } + }; + template<> struct QVariantValueHelperInterface<QVariantList> { static QVariantList invoke(const QVariant &v) @@ -690,6 +801,37 @@ namespace QtPrivate { return QVariantValueHelper<QVariantList>::invoke(v); } }; + template<> + struct QVariantValueHelperInterface<QVariantHash> + { + static QVariantHash invoke(const QVariant &v) + { + if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) { + QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v); + QVariantHash l; + l.reserve(iter.size()); + for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) + l.insert(it.key().toString(), it.value()); + return l; + } + return QVariantValueHelper<QVariantHash>::invoke(v); + } + }; + template<> + struct QVariantValueHelperInterface<QVariantMap> + { + static QVariantMap invoke(const QVariant &v) + { + if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) { + QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v); + QVariantMap l; + for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) + l.insert(it.key().toString(), it.value()); + return l; + } + return QVariantValueHelper<QVariantMap>::invoke(v); + } + }; } template<typename T> inline T qvariant_cast(const QVariant &v) |