diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index fa3398b6bf..cdabf2c6d2 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -1261,6 +1261,60 @@ void *QMetaType::create(int type, const void *copy) return creator(copy); } +namespace { +class TypeDestroyer { + template::IsAccepted> + struct DestroyerImpl { + static void Destroy(const int /* type */, T *where) { delete where; } + }; + template + struct DestroyerImpl { + static void Destroy(const int type, void *where) + { + if (QTypeModuleInfo::IsGui) { + if (qMetaTypeGuiHelper) + qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].deleter(where); + return; + } + if (QTypeModuleInfo::IsWidget) { + if (qMetaTypeWidgetsHelper) + qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].deleter(where); + return; + } + // This point can be reached only for known types that definition is not available, for example + // in bootstrap mode. We have no other choice then ignore it. + } + }; +public: + TypeDestroyer(const int type) + : m_type(type) + {} + + template + void delegate(const T *where) { DestroyerImpl::Destroy(m_type, const_cast(where)); } + void delegate(const void *) {} + void delegate(const QMetaTypeSwitcher::UnknownType *where) { customTypeDestroyer(m_type, (void*)where); } + +private: + static void customTypeDestroyer(const int type, void *where) + { + QMetaType::Destructor deleter; + const QVector * const ct = customTypes(); + { + QReadLocker locker(customTypesLock()); + if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User)) + return; + deleter = ct->at(type - QMetaType::User).deleter; + } + if (Q_LIKELY(deleter)) + deleter(where); + } + + const int m_type; +}; +} // namespace + + /*! Destroys the \a data, assuming it is of the \a type given. @@ -1268,173 +1322,8 @@ void *QMetaType::create(int type, const void *copy) */ void QMetaType::destroy(int type, void *data) { - if (!data) - return; - switch(type) { - case QMetaType::VoidStar: - case QMetaType::QObjectStar: - case QMetaType::QWidgetStar: - delete static_cast(data); - break; - case QMetaType::Long: - delete static_cast(data); - break; - case QMetaType::Int: - delete static_cast(data); - break; - case QMetaType::Short: - delete static_cast(data); - break; - case QMetaType::Char: - delete static_cast(data); - break; - case QMetaType::ULong: - delete static_cast(data); - break; - case QMetaType::LongLong: - delete static_cast(data); - break; - case QMetaType::ULongLong: - delete static_cast(data); - break; - case QMetaType::UInt: - delete static_cast(data); - break; - case QMetaType::UShort: - delete static_cast(data); - break; - case QMetaType::UChar: - delete static_cast(data); - break; - case QMetaType::Bool: - delete static_cast(data); - break; - case QMetaType::Float: - delete static_cast(data); - break; - case QMetaType::Double: - delete static_cast(data); - break; - case QMetaType::QChar: - delete static_cast< NS(QChar)* >(data); - break; -#ifndef QT_BOOTSTRAPPED - case QMetaType::QVariantMap: - delete static_cast< NS(QVariantMap)* >(data); - break; - case QMetaType::QVariantHash: - delete static_cast< NS(QVariantHash)* >(data); - break; - case QMetaType::QVariantList: - delete static_cast< NS(QVariantList)* >(data); - break; - case QMetaType::QVariant: - delete static_cast< NS(QVariant)* >(data); - break; -#endif - case QMetaType::QByteArray: - delete static_cast< NS(QByteArray)* >(data); - break; - case QMetaType::QString: - delete static_cast< NS(QString)* >(data); - break; - case QMetaType::QStringList: - delete static_cast< NS(QStringList)* >(data); - break; -#ifndef QT_BOOTSTRAPPED - case QMetaType::QBitArray: - delete static_cast< NS(QBitArray)* >(data); - break; -#endif - case QMetaType::QDate: - delete static_cast< NS(QDate)* >(data); - break; - case QMetaType::QTime: - delete static_cast< NS(QTime)* >(data); - break; - case QMetaType::QDateTime: - delete static_cast< NS(QDateTime)* >(data); - break; -#ifndef QT_BOOTSTRAPPED - case QMetaType::QUrl: - delete static_cast< NS(QUrl)* >(data); -#endif - break; - case QMetaType::QLocale: - delete static_cast< NS(QLocale)* >(data); - break; -#ifndef QT_NO_GEOM_VARIANT - case QMetaType::QRect: - delete static_cast< NS(QRect)* >(data); - break; - case QMetaType::QRectF: - delete static_cast< NS(QRectF)* >(data); - break; - case QMetaType::QSize: - delete static_cast< NS(QSize)* >(data); - break; - case QMetaType::QSizeF: - delete static_cast< NS(QSizeF)* >(data); - break; - case QMetaType::QLine: - delete static_cast< NS(QLine)* >(data); - break; - case QMetaType::QLineF: - delete static_cast< NS(QLineF)* >(data); - break; - case QMetaType::QPoint: - delete static_cast< NS(QPoint)* >(data); - break; - case QMetaType::QPointF: - delete static_cast< NS(QPointF)* >(data); - break; -#endif -#ifndef QT_NO_REGEXP - case QMetaType::QRegExp: - delete static_cast< NS(QRegExp)* >(data); - break; -#endif -#ifndef QT_BOOTSTRAPPED - case QMetaType::QEasingCurve: - delete static_cast< NS(QEasingCurve)* >(data); - break; -#endif - case QMetaType::QUuid: - delete static_cast< NS(QUuid)* >(data); - break; -#ifndef QT_BOOTSTRAPPED - case QMetaType::QModelIndex: - delete static_cast< NS(QModelIndex)* >(data); - break; -#endif - case QMetaType::Void: - break; - default: { - const QVector * const ct = customTypes(); - Deleter deleter = 0; - if (type >= FirstGuiType && type <= LastGuiType) { - Q_ASSERT(qMetaTypeGuiHelper); - - if (!qMetaTypeGuiHelper) - return; - deleter = qMetaTypeGuiHelper[type - FirstGuiType].deleter; - } else if (type >= FirstWidgetsType && type <= LastWidgetsType) { - Q_ASSERT(qMetaTypeWidgetsHelper); - - if (!qMetaTypeWidgetsHelper) - return; - deleter = qMetaTypeWidgetsHelper[type - FirstWidgetsType].deleter; - } else { - QReadLocker locker(customTypesLock()); - if (type < User || !ct || ct->count() <= type - User) - break; - if (ct->at(type - User).typeName.isEmpty()) - break; - deleter = ct->at(type - User).deleter; - } - deleter(data); - break; } - } + TypeDestroyer deleter(type); + QMetaTypeSwitcher::switcher(deleter, type, data); } namespace {